From 4de5ba8aa883f226d12bd8b5a361012e9f153bd2 Mon Sep 17 00:00:00 2001 From: Guillaume Claret Date: Mon, 9 Dec 2024 17:53:01 +0100 Subject: [PATCH 1/3] wip --- coq/translate.py | 60 + coq/translation/__init__.ast | 18 + coq/translation/__init__.v | 8 + coq/translation/blocks.ast | 284 ++ coq/translation/blocks.v | 19 + coq/translation/bloom.ast | 208 + coq/translation/bloom.v | 23 + coq/translation/exceptions.ast | 72 + coq/translation/exceptions.v | 6 + coq/translation/fork.ast | 3825 +++++++++++++++++ coq/translation/fork.v | 32 + coq/translation/fork_types.ast | 150 + coq/translation/fork_types.v | 19 + coq/translation/state.ast | 2062 +++++++++ coq/translation/state.v | 27 + coq/translation/transactions.ast | 635 +++ coq/translation/transactions.v | 13 + coq/translation/trie.ast | 1646 +++++++ coq/translation/trie.v | 26 + coq/translation/utils/__init__.ast | 5 + coq/translation/utils/__init__.v | 4 + coq/translation/utils/address.ast | 216 + coq/translation/utils/address.v | 21 + coq/translation/utils/hexadecimal.ast | 124 + coq/translation/utils/hexadecimal.v | 17 + coq/translation/utils/message.ast | 335 ++ coq/translation/utils/message.v | 23 + coq/translation/vm/__init__.ast | 612 +++ coq/translation/vm/__init__.v | 24 + coq/translation/vm/exceptions.ast | 185 + coq/translation/vm/exceptions.v | 15 + coq/translation/vm/gas.ast | 1106 +++++ coq/translation/vm/gas.v | 22 + coq/translation/vm/instructions/__init__.ast | 1864 ++++++++ coq/translation/vm/instructions/__init__.v | 16 + .../vm/instructions/arithmetic.ast | 1289 ++++++ coq/translation/vm/instructions/arithmetic.v | 18 + coq/translation/vm/instructions/bitwise.ast | 751 ++++ coq/translation/vm/instructions/bitwise.v | 17 + coq/translation/vm/instructions/block.ast | 495 +++ coq/translation/vm/instructions/block.v | 17 + .../vm/instructions/comparison.ast | 514 +++ coq/translation/vm/instructions/comparison.v | 17 + .../vm/instructions/control_flow.ast | 371 ++ .../vm/instructions/control_flow.v | 18 + .../vm/instructions/environment.ast | 2007 +++++++++ coq/translation/vm/instructions/environment.v | 25 + coq/translation/vm/instructions/keccak.ast | 205 + coq/translation/vm/instructions/keccak.v | 20 + coq/translation/vm/instructions/log.ast | 323 ++ coq/translation/vm/instructions/log.v | 21 + coq/translation/vm/instructions/memory.ast | 632 +++ coq/translation/vm/instructions/memory.v | 20 + coq/translation/vm/instructions/stack.ast | 1110 +++++ coq/translation/vm/instructions/stack.v | 19 + coq/translation/vm/instructions/storage.ast | 731 ++++ coq/translation/vm/instructions/storage.v | 19 + coq/translation/vm/instructions/system.ast | 2952 +++++++++++++ coq/translation/vm/instructions/system.v | 24 + coq/translation/vm/interpreter.ast | 1216 ++++++ coq/translation/vm/interpreter.v | 28 + coq/translation/vm/memory.ast | 148 + coq/translation/vm/memory.v | 17 + .../vm/precompiled_contracts/__init__.ast | 106 + .../vm/precompiled_contracts/__init__.v | 16 + .../vm/precompiled_contracts/alt_bn128.ast | 913 ++++ .../vm/precompiled_contracts/alt_bn128.v | 20 + .../vm/precompiled_contracts/blake2f.ast | 137 + .../vm/precompiled_contracts/blake2f.v | 18 + .../vm/precompiled_contracts/ecrecover.ast | 306 ++ .../vm/precompiled_contracts/ecrecover.v | 21 + .../vm/precompiled_contracts/identity.ast | 96 + .../vm/precompiled_contracts/identity.v | 18 + .../vm/precompiled_contracts/mapping.ast | 105 + .../vm/precompiled_contracts/mapping.v | 24 + .../vm/precompiled_contracts/modexp.ast | 638 +++ .../vm/precompiled_contracts/modexp.v | 19 + .../point_evaluation.ast | 240 ++ .../precompiled_contracts/point_evaluation.v | 20 + .../vm/precompiled_contracts/ripemd160.ast | 131 + .../vm/precompiled_contracts/ripemd160.v | 19 + .../vm/precompiled_contracts/sha256.ast | 112 + .../vm/precompiled_contracts/sha256.v | 18 + coq/translation/vm/runtime.ast | 180 + coq/translation/vm/runtime.v | 17 + coq/translation/vm/stack.ast | 109 + coq/translation/vm/stack.v | 17 + 87 files changed, 30046 insertions(+) create mode 100644 coq/translate.py create mode 100644 coq/translation/__init__.ast create mode 100644 coq/translation/__init__.v create mode 100644 coq/translation/blocks.ast create mode 100644 coq/translation/blocks.v create mode 100644 coq/translation/bloom.ast create mode 100644 coq/translation/bloom.v create mode 100644 coq/translation/exceptions.ast create mode 100644 coq/translation/exceptions.v create mode 100644 coq/translation/fork.ast create mode 100644 coq/translation/fork.v create mode 100644 coq/translation/fork_types.ast create mode 100644 coq/translation/fork_types.v create mode 100644 coq/translation/state.ast create mode 100644 coq/translation/state.v create mode 100644 coq/translation/transactions.ast create mode 100644 coq/translation/transactions.v create mode 100644 coq/translation/trie.ast create mode 100644 coq/translation/trie.v create mode 100644 coq/translation/utils/__init__.ast create mode 100644 coq/translation/utils/__init__.v create mode 100644 coq/translation/utils/address.ast create mode 100644 coq/translation/utils/address.v create mode 100644 coq/translation/utils/hexadecimal.ast create mode 100644 coq/translation/utils/hexadecimal.v create mode 100644 coq/translation/utils/message.ast create mode 100644 coq/translation/utils/message.v create mode 100644 coq/translation/vm/__init__.ast create mode 100644 coq/translation/vm/__init__.v create mode 100644 coq/translation/vm/exceptions.ast create mode 100644 coq/translation/vm/exceptions.v create mode 100644 coq/translation/vm/gas.ast create mode 100644 coq/translation/vm/gas.v create mode 100644 coq/translation/vm/instructions/__init__.ast create mode 100644 coq/translation/vm/instructions/__init__.v create mode 100644 coq/translation/vm/instructions/arithmetic.ast create mode 100644 coq/translation/vm/instructions/arithmetic.v create mode 100644 coq/translation/vm/instructions/bitwise.ast create mode 100644 coq/translation/vm/instructions/bitwise.v create mode 100644 coq/translation/vm/instructions/block.ast create mode 100644 coq/translation/vm/instructions/block.v create mode 100644 coq/translation/vm/instructions/comparison.ast create mode 100644 coq/translation/vm/instructions/comparison.v create mode 100644 coq/translation/vm/instructions/control_flow.ast create mode 100644 coq/translation/vm/instructions/control_flow.v create mode 100644 coq/translation/vm/instructions/environment.ast create mode 100644 coq/translation/vm/instructions/environment.v create mode 100644 coq/translation/vm/instructions/keccak.ast create mode 100644 coq/translation/vm/instructions/keccak.v create mode 100644 coq/translation/vm/instructions/log.ast create mode 100644 coq/translation/vm/instructions/log.v create mode 100644 coq/translation/vm/instructions/memory.ast create mode 100644 coq/translation/vm/instructions/memory.v create mode 100644 coq/translation/vm/instructions/stack.ast create mode 100644 coq/translation/vm/instructions/stack.v create mode 100644 coq/translation/vm/instructions/storage.ast create mode 100644 coq/translation/vm/instructions/storage.v create mode 100644 coq/translation/vm/instructions/system.ast create mode 100644 coq/translation/vm/instructions/system.v create mode 100644 coq/translation/vm/interpreter.ast create mode 100644 coq/translation/vm/interpreter.v create mode 100644 coq/translation/vm/memory.ast create mode 100644 coq/translation/vm/memory.v create mode 100644 coq/translation/vm/precompiled_contracts/__init__.ast create mode 100644 coq/translation/vm/precompiled_contracts/__init__.v create mode 100644 coq/translation/vm/precompiled_contracts/alt_bn128.ast create mode 100644 coq/translation/vm/precompiled_contracts/alt_bn128.v create mode 100644 coq/translation/vm/precompiled_contracts/blake2f.ast create mode 100644 coq/translation/vm/precompiled_contracts/blake2f.v create mode 100644 coq/translation/vm/precompiled_contracts/ecrecover.ast create mode 100644 coq/translation/vm/precompiled_contracts/ecrecover.v create mode 100644 coq/translation/vm/precompiled_contracts/identity.ast create mode 100644 coq/translation/vm/precompiled_contracts/identity.v create mode 100644 coq/translation/vm/precompiled_contracts/mapping.ast create mode 100644 coq/translation/vm/precompiled_contracts/mapping.v create mode 100644 coq/translation/vm/precompiled_contracts/modexp.ast create mode 100644 coq/translation/vm/precompiled_contracts/modexp.v create mode 100644 coq/translation/vm/precompiled_contracts/point_evaluation.ast create mode 100644 coq/translation/vm/precompiled_contracts/point_evaluation.v create mode 100644 coq/translation/vm/precompiled_contracts/ripemd160.ast create mode 100644 coq/translation/vm/precompiled_contracts/ripemd160.v create mode 100644 coq/translation/vm/precompiled_contracts/sha256.ast create mode 100644 coq/translation/vm/precompiled_contracts/sha256.v create mode 100644 coq/translation/vm/runtime.ast create mode 100644 coq/translation/vm/runtime.v create mode 100644 coq/translation/vm/stack.ast create mode 100644 coq/translation/vm/stack.v diff --git a/coq/translate.py b/coq/translate.py new file mode 100644 index 0000000000..585b81a789 --- /dev/null +++ b/coq/translate.py @@ -0,0 +1,60 @@ +""" +Translate the Python source code of the EVM to Coq +""" +import ast +from pathlib import Path + + +# For now, we only translate the Cancun version +source_root_dir = Path("../src/ethereum/cancun") + + +def to_coq(tree: ast.AST) -> str: + if isinstance(tree, ast.Module): + output = "" + + if len(tree.body) >= 1 and \ + isinstance(tree.body[0], ast.Expr) and \ + isinstance(tree.body[0].value, ast.Constant): + output += f"(*{tree.body[0].value.value}*)\n\n" + else: + return "No description available at the beginning of the file" + + import_aliases: dict[str, str] = {} + for node in tree.body[1:]: + if isinstance(node, ast.ImportFrom): + if node.module is not None: + for alias in node.names: + import_aliases[alias.name] = node.module + output += f"Require {node.module}.\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 = Path("translation") / 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(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) diff --git a/coq/translation/__init__.ast b/coq/translation/__init__.ast new file mode 100644 index 0000000000..cedcfc26d3 --- /dev/null +++ b/coq/translation/__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/translation/__init__.v b/coq/translation/__init__.v new file mode 100644 index 0000000000..dc74124bf2 --- /dev/null +++ b/coq/translation/__init__.v @@ -0,0 +1,8 @@ +(* +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/translation/blocks.ast b/coq/translation/blocks.ast new file mode 100644 index 0000000000..a05f4e7a06 --- /dev/null +++ b/coq/translation/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/translation/blocks.v b/coq/translation/blocks.v new file mode 100644 index 0000000000..5ebd4d4748 --- /dev/null +++ b/coq/translation/blocks.v @@ -0,0 +1,19 @@ +(* +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 crypto.hash. +Require fork_types. +Require transactions. diff --git a/coq/translation/bloom.ast b/coq/translation/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/translation/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/translation/bloom.v b/coq/translation/bloom.v new file mode 100644 index 0000000000..1e3fd0cf86 --- /dev/null +++ b/coq/translation/bloom.v @@ -0,0 +1,23 @@ +(* +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 blocks. +Require fork_types. diff --git a/coq/translation/exceptions.ast b/coq/translation/exceptions.ast new file mode 100644 index 0000000000..a61ee25448 --- /dev/null +++ b/coq/translation/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/translation/exceptions.v b/coq/translation/exceptions.v new file mode 100644 index 0000000000..137ea143f6 --- /dev/null +++ b/coq/translation/exceptions.v @@ -0,0 +1,6 @@ +(* +Exceptions specific to this fork. +*) + +Require typing. +Require ethereum.exceptions. diff --git a/coq/translation/fork.ast b/coq/translation/fork.ast new file mode 100644 index 0000000000..406c401cf5 --- /dev/null +++ b/coq/translation/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/translation/fork.v b/coq/translation/fork.v new file mode 100644 index 0000000000..ae0cd5f2cd --- /dev/null +++ b/coq/translation/fork.v @@ -0,0 +1,32 @@ +(* +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 blocks. +Require bloom. +Require fork_types. +Require state. +Require transactions. +Require trie. +Require utils.hexadecimal. +Require utils.message. +Require vm. +Require vm.gas. +Require vm.interpreter. diff --git a/coq/translation/fork_types.ast b/coq/translation/fork_types.ast new file mode 100644 index 0000000000..4f0e4e29ac --- /dev/null +++ b/coq/translation/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/translation/fork_types.v b/coq/translation/fork_types.v new file mode 100644 index 0000000000..f8294e1e51 --- /dev/null +++ b/coq/translation/fork_types.v @@ -0,0 +1,19 @@ +(* +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 crypto.hash. diff --git a/coq/translation/state.ast b/coq/translation/state.ast new file mode 100644 index 0000000000..f87ed536d5 --- /dev/null +++ b/coq/translation/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/translation/state.v b/coq/translation/state.v new file mode 100644 index 0000000000..f728b5afab --- /dev/null +++ b/coq/translation/state.v @@ -0,0 +1,27 @@ +(* +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 blocks. +Require fork_types. +Require trie. diff --git a/coq/translation/transactions.ast b/coq/translation/transactions.ast new file mode 100644 index 0000000000..1ba3903365 --- /dev/null +++ b/coq/translation/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/translation/transactions.v b/coq/translation/transactions.v new file mode 100644 index 0000000000..79554e3955 --- /dev/null +++ b/coq/translation/transactions.v @@ -0,0 +1,13 @@ +(* +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 exceptions. +Require fork_types. diff --git a/coq/translation/trie.ast b/coq/translation/trie.ast new file mode 100644 index 0000000000..998cc53d11 --- /dev/null +++ b/coq/translation/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/translation/trie.v b/coq/translation/trie.v new file mode 100644 index 0000000000..c2223b9ad3 --- /dev/null +++ b/coq/translation/trie.v @@ -0,0 +1,26 @@ +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.shanghai. +Require ethereum.utils.hexadecimal. +Require blocks. +Require fork_types. +Require transactions. diff --git a/coq/translation/utils/__init__.ast b/coq/translation/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/translation/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/translation/utils/__init__.v b/coq/translation/utils/__init__.v new file mode 100644 index 0000000000..beff4482b1 --- /dev/null +++ b/coq/translation/utils/__init__.v @@ -0,0 +1,4 @@ +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/translation/utils/address.ast b/coq/translation/utils/address.ast new file mode 100644 index 0000000000..a94a759c63 --- /dev/null +++ b/coq/translation/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/translation/utils/address.v b/coq/translation/utils/address.v new file mode 100644 index 0000000000..981ef4b450 --- /dev/null +++ b/coq/translation/utils/address.v @@ -0,0 +1,21 @@ +(* +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 fork_types. diff --git a/coq/translation/utils/hexadecimal.ast b/coq/translation/utils/hexadecimal.ast new file mode 100644 index 0000000000..2f53dc38ab --- /dev/null +++ b/coq/translation/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/translation/utils/hexadecimal.v b/coq/translation/utils/hexadecimal.v new file mode 100644 index 0000000000..6cc4882945 --- /dev/null +++ b/coq/translation/utils/hexadecimal.v @@ -0,0 +1,17 @@ +(* +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 fork_types. diff --git a/coq/translation/utils/message.ast b/coq/translation/utils/message.ast new file mode 100644 index 0000000000..1bcbe39833 --- /dev/null +++ b/coq/translation/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/translation/utils/message.v b/coq/translation/utils/message.v new file mode 100644 index 0000000000..0b1cdb7cd8 --- /dev/null +++ b/coq/translation/utils/message.v @@ -0,0 +1,23 @@ +(* +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 fork_types. +Require state. +Require vm. +Require vm.precompiled_contracts.mapping. +Require address. diff --git a/coq/translation/vm/__init__.ast b/coq/translation/vm/__init__.ast new file mode 100644 index 0000000000..7f5c7f4b15 --- /dev/null +++ b/coq/translation/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/translation/vm/__init__.v b/coq/translation/vm/__init__.v new file mode 100644 index 0000000000..9487aa222b --- /dev/null +++ b/coq/translation/vm/__init__.v @@ -0,0 +1,24 @@ +(* +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 blocks. +Require fork_types. +Require state. +Require precompiled_contracts. diff --git a/coq/translation/vm/exceptions.ast b/coq/translation/vm/exceptions.ast new file mode 100644 index 0000000000..1665dd8581 --- /dev/null +++ b/coq/translation/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/translation/vm/exceptions.v b/coq/translation/vm/exceptions.v new file mode 100644 index 0000000000..1784494410 --- /dev/null +++ b/coq/translation/vm/exceptions.v @@ -0,0 +1,15 @@ +(* +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/translation/vm/gas.ast b/coq/translation/vm/gas.ast new file mode 100644 index 0000000000..f41eff4bb8 --- /dev/null +++ b/coq/translation/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/translation/vm/gas.v b/coq/translation/vm/gas.v new file mode 100644 index 0000000000..2f8165fe9f --- /dev/null +++ b/coq/translation/vm/gas.v @@ -0,0 +1,22 @@ +(* +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 blocks. +Require transactions. +Require exceptions. diff --git a/coq/translation/vm/instructions/__init__.ast b/coq/translation/vm/instructions/__init__.ast new file mode 100644 index 0000000000..b5ae8c5daf --- /dev/null +++ b/coq/translation/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/translation/vm/instructions/__init__.v b/coq/translation/vm/instructions/__init__.v new file mode 100644 index 0000000000..8a859b1645 --- /dev/null +++ b/coq/translation/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + +Require typing. diff --git a/coq/translation/vm/instructions/arithmetic.ast b/coq/translation/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/translation/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/translation/vm/instructions/arithmetic.v b/coq/translation/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..a4d756f9b4 --- /dev/null +++ b/coq/translation/vm/instructions/arithmetic.v @@ -0,0 +1,18 @@ +(* +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 gas. +Require stack. diff --git a/coq/translation/vm/instructions/bitwise.ast b/coq/translation/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..b72397f0ec --- /dev/null +++ b/coq/translation/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/translation/vm/instructions/bitwise.v b/coq/translation/vm/instructions/bitwise.v new file mode 100644 index 0000000000..ea6e70dd9e --- /dev/null +++ b/coq/translation/vm/instructions/bitwise.v @@ -0,0 +1,17 @@ +(* +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 gas. +Require stack. diff --git a/coq/translation/vm/instructions/block.ast b/coq/translation/vm/instructions/block.ast new file mode 100644 index 0000000000..ca57ef8a6a --- /dev/null +++ b/coq/translation/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/translation/vm/instructions/block.v b/coq/translation/vm/instructions/block.v new file mode 100644 index 0000000000..e247e24b18 --- /dev/null +++ b/coq/translation/vm/instructions/block.v @@ -0,0 +1,17 @@ +(* +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 gas. +Require stack. diff --git a/coq/translation/vm/instructions/comparison.ast b/coq/translation/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/translation/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/translation/vm/instructions/comparison.v b/coq/translation/vm/instructions/comparison.v new file mode 100644 index 0000000000..2bd22cc9f3 --- /dev/null +++ b/coq/translation/vm/instructions/comparison.v @@ -0,0 +1,17 @@ +(* +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 gas. +Require stack. diff --git a/coq/translation/vm/instructions/control_flow.ast b/coq/translation/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/translation/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/translation/vm/instructions/control_flow.v b/coq/translation/vm/instructions/control_flow.v new file mode 100644 index 0000000000..94774f38be --- /dev/null +++ b/coq/translation/vm/instructions/control_flow.v @@ -0,0 +1,18 @@ +(* +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 vm.gas. +Require exceptions. +Require stack. diff --git a/coq/translation/vm/instructions/environment.ast b/coq/translation/vm/instructions/environment.ast new file mode 100644 index 0000000000..f0ddc073d0 --- /dev/null +++ b/coq/translation/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/translation/vm/instructions/environment.v b/coq/translation/vm/instructions/environment.v new file mode 100644 index 0000000000..6afbd5a29c --- /dev/null +++ b/coq/translation/vm/instructions/environment.v @@ -0,0 +1,25 @@ +(* +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 fork_types. +Require state. +Require utils.address. +Require vm.memory. +Require exceptions. +Require gas. +Require stack. diff --git a/coq/translation/vm/instructions/keccak.ast b/coq/translation/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/translation/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/translation/vm/instructions/keccak.v b/coq/translation/vm/instructions/keccak.v new file mode 100644 index 0000000000..31fe83edc4 --- /dev/null +++ b/coq/translation/vm/instructions/keccak.v @@ -0,0 +1,20 @@ +(* +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 gas. +Require memory. +Require stack. diff --git a/coq/translation/vm/instructions/log.ast b/coq/translation/vm/instructions/log.ast new file mode 100644 index 0000000000..0ded0e04ba --- /dev/null +++ b/coq/translation/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/translation/vm/instructions/log.v b/coq/translation/vm/instructions/log.v new file mode 100644 index 0000000000..f9f59c7815 --- /dev/null +++ b/coq/translation/vm/instructions/log.v @@ -0,0 +1,21 @@ +(* +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 blocks. +Require exceptions. +Require gas. +Require memory. +Require stack. diff --git a/coq/translation/vm/instructions/memory.ast b/coq/translation/vm/instructions/memory.ast new file mode 100644 index 0000000000..8c10178d17 --- /dev/null +++ b/coq/translation/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/translation/vm/instructions/memory.v b/coq/translation/vm/instructions/memory.v new file mode 100644 index 0000000000..7cc1083cbe --- /dev/null +++ b/coq/translation/vm/instructions/memory.v @@ -0,0 +1,20 @@ +(* +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 gas. +Require memory. +Require stack. diff --git a/coq/translation/vm/instructions/stack.ast b/coq/translation/vm/instructions/stack.ast new file mode 100644 index 0000000000..79c3c451b2 --- /dev/null +++ b/coq/translation/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/translation/vm/instructions/stack.v b/coq/translation/vm/instructions/stack.v new file mode 100644 index 0000000000..03a464f8c2 --- /dev/null +++ b/coq/translation/vm/instructions/stack.v @@ -0,0 +1,19 @@ +(* +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 exceptions. +Require gas. +Require memory. diff --git a/coq/translation/vm/instructions/storage.ast b/coq/translation/vm/instructions/storage.ast new file mode 100644 index 0000000000..a3e90e6e70 --- /dev/null +++ b/coq/translation/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/translation/vm/instructions/storage.v b/coq/translation/vm/instructions/storage.v new file mode 100644 index 0000000000..d7c600ac9a --- /dev/null +++ b/coq/translation/vm/instructions/storage.v @@ -0,0 +1,19 @@ +(* +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 state. +Require exceptions. +Require gas. +Require stack. diff --git a/coq/translation/vm/instructions/system.ast b/coq/translation/vm/instructions/system.ast new file mode 100644 index 0000000000..63ad6f071b --- /dev/null +++ b/coq/translation/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/translation/vm/instructions/system.v b/coq/translation/vm/instructions/system.v new file mode 100644 index 0000000000..27a34c527d --- /dev/null +++ b/coq/translation/vm/instructions/system.v @@ -0,0 +1,24 @@ +(* +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 fork_types. +Require state. +Require utils.address. +Require exceptions. +Require gas. +Require memory. +Require stack. diff --git a/coq/translation/vm/interpreter.ast b/coq/translation/vm/interpreter.ast new file mode 100644 index 0000000000..4ec2cfea34 --- /dev/null +++ b/coq/translation/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/translation/vm/interpreter.v b/coq/translation/vm/interpreter.v new file mode 100644 index 0000000000..b093bdbc21 --- /dev/null +++ b/coq/translation/vm/interpreter.v @@ -0,0 +1,28 @@ +(* +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 blocks. +Require fork_types. +Require state. +Require vm. +Require vm.gas. +Require vm.precompiled_contracts.mapping. +Require exceptions. +Require instructions. +Require runtime. diff --git a/coq/translation/vm/memory.ast b/coq/translation/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/translation/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/translation/vm/memory.v b/coq/translation/vm/memory.v new file mode 100644 index 0000000000..6c7452b03c --- /dev/null +++ b/coq/translation/vm/memory.v @@ -0,0 +1,17 @@ +(* +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. diff --git a/coq/translation/vm/precompiled_contracts/__init__.ast b/coq/translation/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..cfca73a3bd --- /dev/null +++ b/coq/translation/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/translation/vm/precompiled_contracts/__init__.v b/coq/translation/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..767782fbe3 --- /dev/null +++ b/coq/translation/vm/precompiled_contracts/__init__.v @@ -0,0 +1,16 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require utils.hexadecimal. diff --git a/coq/translation/vm/precompiled_contracts/alt_bn128.ast b/coq/translation/vm/precompiled_contracts/alt_bn128.ast new file mode 100644 index 0000000000..f6f077419c --- /dev/null +++ b/coq/translation/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/translation/vm/precompiled_contracts/alt_bn128.v b/coq/translation/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000000..e7280f928c --- /dev/null +++ b/coq/translation/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,20 @@ +(* +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 vm. +Require vm.gas. +Require vm.memory. +Require exceptions. diff --git a/coq/translation/vm/precompiled_contracts/blake2f.ast b/coq/translation/vm/precompiled_contracts/blake2f.ast new file mode 100644 index 0000000000..03747962f0 --- /dev/null +++ b/coq/translation/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/translation/vm/precompiled_contracts/blake2f.v b/coq/translation/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000000..9fe88931a3 --- /dev/null +++ b/coq/translation/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,18 @@ +(* +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 vm. +Require vm.gas. +Require exceptions. diff --git a/coq/translation/vm/precompiled_contracts/ecrecover.ast b/coq/translation/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/translation/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/translation/vm/precompiled_contracts/ecrecover.v b/coq/translation/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..c2a5513b6a --- /dev/null +++ b/coq/translation/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,21 @@ +(* +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 vm. +Require vm.gas. +Require vm.memory. diff --git a/coq/translation/vm/precompiled_contracts/identity.ast b/coq/translation/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/translation/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/translation/vm/precompiled_contracts/identity.v b/coq/translation/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..d4ff1d30e2 --- /dev/null +++ b/coq/translation/vm/precompiled_contracts/identity.v @@ -0,0 +1,18 @@ +(* +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 vm. +Require vm.gas. diff --git a/coq/translation/vm/precompiled_contracts/mapping.ast b/coq/translation/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..298eeda974 --- /dev/null +++ b/coq/translation/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/translation/vm/precompiled_contracts/mapping.v b/coq/translation/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..572105c4fb --- /dev/null +++ b/coq/translation/vm/precompiled_contracts/mapping.v @@ -0,0 +1,24 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require fork_types. +Require alt_bn128. +Require blake2f. +Require ecrecover. +Require identity. +Require modexp. +Require point_evaluation. +Require ripemd160. +Require sha256. diff --git a/coq/translation/vm/precompiled_contracts/modexp.ast b/coq/translation/vm/precompiled_contracts/modexp.ast new file mode 100644 index 0000000000..42ecfa223f --- /dev/null +++ b/coq/translation/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/translation/vm/precompiled_contracts/modexp.v b/coq/translation/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000000..39b7b43c10 --- /dev/null +++ b/coq/translation/vm/precompiled_contracts/modexp.v @@ -0,0 +1,19 @@ +(* +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 vm. +Require vm.gas. +Require memory. diff --git a/coq/translation/vm/precompiled_contracts/point_evaluation.ast b/coq/translation/vm/precompiled_contracts/point_evaluation.ast new file mode 100644 index 0000000000..af245ad3c5 --- /dev/null +++ b/coq/translation/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/translation/vm/precompiled_contracts/point_evaluation.v b/coq/translation/vm/precompiled_contracts/point_evaluation.v new file mode 100644 index 0000000000..a3eea74ad1 --- /dev/null +++ b/coq/translation/vm/precompiled_contracts/point_evaluation.v @@ -0,0 +1,20 @@ +(* +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 vm. +Require vm.exceptions. +Require vm.gas. diff --git a/coq/translation/vm/precompiled_contracts/ripemd160.ast b/coq/translation/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/translation/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/translation/vm/precompiled_contracts/ripemd160.v b/coq/translation/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..ca9692600a --- /dev/null +++ b/coq/translation/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,19 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.byte. +Require ethereum.utils.numeric. +Require vm. +Require vm.gas. diff --git a/coq/translation/vm/precompiled_contracts/sha256.ast b/coq/translation/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/translation/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/translation/vm/precompiled_contracts/sha256.v b/coq/translation/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..e62d067223 --- /dev/null +++ b/coq/translation/vm/precompiled_contracts/sha256.v @@ -0,0 +1,18 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require vm. +Require vm.gas. diff --git a/coq/translation/vm/runtime.ast b/coq/translation/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/translation/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/translation/vm/runtime.v b/coq/translation/vm/runtime.v new file mode 100644 index 0000000000..38094eefa0 --- /dev/null +++ b/coq/translation/vm/runtime.v @@ -0,0 +1,17 @@ +(* +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 instructions. diff --git a/coq/translation/vm/stack.ast b/coq/translation/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/translation/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/translation/vm/stack.v b/coq/translation/vm/stack.v new file mode 100644 index 0000000000..d9409b7870 --- /dev/null +++ b/coq/translation/vm/stack.v @@ -0,0 +1,17 @@ +(* +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 exceptions. From a03e4c064d707202001ab1bad90d50eca277586a Mon Sep 17 00:00:00 2001 From: Guillaume Claret Date: Tue, 10 Dec 2024 10:52:06 +0100 Subject: [PATCH 2/3] more wip --- coq/ethereum/__init__.ast | 39 + coq/ethereum/__init__.v | 19 + coq/ethereum/arrow_glacier/__init__.ast | 18 + coq/ethereum/arrow_glacier/__init__.v | 6 + coq/ethereum/arrow_glacier/blocks.ast | 230 + coq/ethereum/arrow_glacier/blocks.v | 19 + .../arrow_glacier}/bloom.ast | 0 coq/ethereum/arrow_glacier/bloom.v | 66 + .../arrow_glacier}/exceptions.ast | 0 .../arrow_glacier}/exceptions.v | 0 coq/ethereum/arrow_glacier/fork.ast | 3991 ++++++++++++++++ coq/ethereum/arrow_glacier/fork.v | 847 ++++ coq/ethereum/arrow_glacier/fork_types.ast | 146 + .../arrow_glacier}/fork_types.v | 12 +- coq/ethereum/arrow_glacier/state.ast | 1692 +++++++ coq/ethereum/arrow_glacier/state.v | 593 +++ coq/ethereum/arrow_glacier/transactions.ast | 492 ++ coq/ethereum/arrow_glacier/transactions.v | 27 + coq/ethereum/arrow_glacier/trie.ast | 1632 +++++++ coq/ethereum/arrow_glacier/trie.v | 274 ++ .../arrow_glacier}/utils/__init__.ast | 0 .../arrow_glacier}/utils/__init__.v | 0 coq/ethereum/arrow_glacier/utils/address.ast | 216 + coq/ethereum/arrow_glacier/utils/address.v | 99 + .../arrow_glacier/utils/hexadecimal.ast | 124 + .../arrow_glacier/utils/hexadecimal.v | 68 + coq/ethereum/arrow_glacier/utils/message.ast | 335 ++ coq/ethereum/arrow_glacier/utils/message.v | 82 + coq/ethereum/arrow_glacier/vm/__init__.ast | 591 +++ coq/ethereum/arrow_glacier/vm/__init__.v | 69 + coq/ethereum/arrow_glacier/vm/exceptions.ast | 175 + .../arrow_glacier}/vm/exceptions.v | 0 coq/ethereum/arrow_glacier/vm/gas.ast | 813 ++++ coq/ethereum/arrow_glacier/vm/gas.v | 151 + .../vm/instructions/__init__.ast | 1792 ++++++++ .../arrow_glacier}/vm/instructions/__init__.v | 1 - .../vm/instructions/arithmetic.ast | 0 .../vm/instructions/arithmetic.v | 387 ++ .../vm/instructions/bitwise.ast | 0 .../arrow_glacier/vm/instructions/bitwise.v | 245 + .../arrow_glacier/vm/instructions/block.ast | 492 ++ .../arrow_glacier/vm/instructions/block.v | 207 + .../vm/instructions/comparison.ast | 0 .../vm/instructions/comparison.v | 206 + .../vm/instructions/control_flow.ast | 0 .../vm/instructions/control_flow.v | 156 + .../vm/instructions/environment.ast | 1828 ++++++++ .../vm/instructions/environment.v | 568 +++ .../arrow_glacier}/vm/instructions/keccak.ast | 0 .../arrow_glacier/vm/instructions/keccak.v | 67 + .../arrow_glacier}/vm/instructions/log.ast | 0 .../arrow_glacier/vm/instructions/log.v | 61 + .../arrow_glacier/vm/instructions/memory.ast | 463 ++ .../arrow_glacier/vm/instructions/memory.v | 158 + .../arrow_glacier/vm/instructions/stack.ast | 1083 +++++ .../arrow_glacier/vm/instructions/stack.v | 133 + .../arrow_glacier/vm/instructions/storage.ast | 551 +++ .../arrow_glacier/vm/instructions/storage.v | 97 + .../arrow_glacier/vm/instructions/system.ast | 2897 ++++++++++++ .../arrow_glacier/vm/instructions/system.v | 585 +++ coq/ethereum/arrow_glacier/vm/interpreter.ast | 1177 +++++ coq/ethereum/arrow_glacier/vm/interpreter.v | 159 + .../arrow_glacier}/vm/memory.ast | 0 coq/ethereum/arrow_glacier/vm/memory.v | 75 + .../vm/precompiled_contracts/__init__.ast | 97 + .../vm/precompiled_contracts/__init__.v | 16 + .../vm/precompiled_contracts/alt_bn128.ast | 0 .../vm/precompiled_contracts/alt_bn128.v | 187 + .../vm/precompiled_contracts/blake2f.ast | 0 .../vm/precompiled_contracts/blake2f.v | 41 + .../vm/precompiled_contracts/ecrecover.ast | 0 .../vm/precompiled_contracts/ecrecover.v | 93 + .../vm/precompiled_contracts/identity.ast | 0 .../vm/precompiled_contracts/identity.v | 36 + .../vm/precompiled_contracts/mapping.ast | 97 + .../vm/precompiled_contracts/mapping.v | 23 + .../vm/precompiled_contracts/modexp.ast | 0 .../vm/precompiled_contracts/modexp.v | 203 + .../vm/precompiled_contracts/ripemd160.ast | 0 .../vm/precompiled_contracts/ripemd160.v | 42 + .../vm/precompiled_contracts/sha256.ast | 0 .../vm/precompiled_contracts/sha256.v | 32 + .../arrow_glacier}/vm/runtime.ast | 0 coq/ethereum/arrow_glacier/vm/runtime.v | 49 + .../arrow_glacier}/vm/stack.ast | 0 coq/ethereum/arrow_glacier/vm/stack.v | 53 + coq/ethereum/berlin/__init__.ast | 18 + coq/ethereum/berlin/__init__.v | 7 + coq/ethereum/berlin/blocks.ast | 226 + coq/ethereum/berlin/blocks.v | 19 + coq/ethereum/berlin/bloom.ast | 208 + coq/ethereum/berlin/bloom.v | 66 + coq/ethereum/berlin/exceptions.ast | 72 + coq/ethereum/berlin/exceptions.v | 6 + coq/ethereum/berlin/fork.ast | 3477 ++++++++++++++ coq/ethereum/berlin/fork.v | 786 ++++ coq/ethereum/berlin/fork_types.ast | 146 + coq/ethereum/berlin/fork_types.v | 29 + coq/ethereum/berlin/state.ast | 1692 +++++++ coq/ethereum/berlin/state.v | 593 +++ coq/ethereum/berlin/transactions.ast | 358 ++ coq/ethereum/berlin/transactions.v | 27 + coq/ethereum/berlin/trie.ast | 1632 +++++++ coq/ethereum/berlin/trie.v | 274 ++ coq/ethereum/berlin/utils/__init__.ast | 5 + coq/ethereum/berlin/utils/__init__.v | 4 + coq/ethereum/berlin/utils/address.ast | 216 + coq/ethereum/berlin/utils/address.v | 99 + coq/ethereum/berlin/utils/hexadecimal.ast | 124 + coq/ethereum/berlin/utils/hexadecimal.v | 68 + coq/ethereum/berlin/utils/message.ast | 335 ++ coq/ethereum/berlin/utils/message.v | 82 + coq/ethereum/berlin/vm/__init__.ast | 587 +++ coq/ethereum/berlin/vm/__init__.v | 69 + coq/ethereum/berlin/vm/exceptions.ast | 165 + coq/ethereum/berlin/vm/exceptions.v | 15 + coq/ethereum/berlin/vm/gas.ast | 817 ++++ coq/ethereum/berlin/vm/gas.v | 151 + .../berlin/vm/instructions/__init__.ast | 1780 ++++++++ .../berlin/vm/instructions/__init__.v | 15 + .../berlin/vm/instructions/arithmetic.ast | 1289 ++++++ .../berlin/vm/instructions/arithmetic.v | 387 ++ .../berlin/vm/instructions/bitwise.ast | 751 +++ coq/ethereum/berlin/vm/instructions/bitwise.v | 245 + coq/ethereum/berlin/vm/instructions/block.ast | 492 ++ coq/ethereum/berlin/vm/instructions/block.v | 207 + .../berlin/vm/instructions/comparison.ast | 514 +++ .../berlin/vm/instructions/comparison.v | 206 + .../berlin/vm/instructions/control_flow.ast | 371 ++ .../berlin/vm/instructions/control_flow.v | 156 + .../berlin/vm/instructions/environment.ast | 1773 ++++++++ .../berlin/vm/instructions/environment.v | 544 +++ .../berlin/vm/instructions/keccak.ast | 205 + coq/ethereum/berlin/vm/instructions/keccak.v | 67 + coq/ethereum/berlin/vm/instructions/log.ast | 323 ++ coq/ethereum/berlin/vm/instructions/log.v | 61 + .../berlin/vm/instructions/memory.ast | 463 ++ coq/ethereum/berlin/vm/instructions/memory.v | 158 + coq/ethereum/berlin/vm/instructions/stack.ast | 1083 +++++ coq/ethereum/berlin/vm/instructions/stack.v | 133 + .../berlin/vm/instructions/storage.ast | 551 +++ coq/ethereum/berlin/vm/instructions/storage.v | 97 + .../berlin/vm/instructions/system.ast | 2962 ++++++++++++ coq/ethereum/berlin/vm/instructions/system.v | 589 +++ coq/ethereum/berlin/vm/interpreter.ast | 1149 +++++ coq/ethereum/berlin/vm/interpreter.v | 159 + coq/ethereum/berlin/vm/memory.ast | 148 + coq/ethereum/berlin/vm/memory.v | 75 + .../vm/precompiled_contracts/__init__.ast | 97 + .../vm/precompiled_contracts/__init__.v | 16 + .../vm/precompiled_contracts/alt_bn128.ast | 913 ++++ .../vm/precompiled_contracts/alt_bn128.v | 187 + .../vm/precompiled_contracts/blake2f.ast | 137 + .../berlin/vm/precompiled_contracts/blake2f.v | 41 + .../vm/precompiled_contracts/ecrecover.ast | 306 ++ .../vm/precompiled_contracts/ecrecover.v | 93 + .../vm/precompiled_contracts/identity.ast | 96 + .../vm/precompiled_contracts/identity.v | 36 + .../vm/precompiled_contracts/mapping.ast | 97 + .../berlin/vm/precompiled_contracts/mapping.v | 23 + .../vm/precompiled_contracts/modexp.ast | 638 +++ .../berlin/vm/precompiled_contracts/modexp.v | 203 + .../vm/precompiled_contracts/ripemd160.ast | 131 + .../vm/precompiled_contracts/ripemd160.v | 42 + .../vm/precompiled_contracts/sha256.ast | 112 + .../berlin/vm/precompiled_contracts/sha256.v | 32 + coq/ethereum/berlin/vm/runtime.ast | 180 + coq/ethereum/berlin/vm/runtime.v | 49 + coq/ethereum/berlin/vm/stack.ast | 109 + coq/ethereum/berlin/vm/stack.v | 53 + coq/ethereum/byzantium/__init__.ast | 18 + coq/ethereum/byzantium/__init__.v | 7 + coq/ethereum/byzantium/blocks.ast | 218 + coq/ethereum/byzantium/blocks.v | 19 + coq/ethereum/byzantium/bloom.ast | 208 + coq/ethereum/byzantium/bloom.v | 66 + coq/ethereum/byzantium/fork.ast | 3186 +++++++++++++ coq/ethereum/byzantium/fork.v | 760 ++++ coq/ethereum/byzantium/fork_types.ast | 146 + coq/ethereum/byzantium/fork_types.v | 29 + coq/ethereum/byzantium/state.ast | 1500 ++++++ coq/ethereum/byzantium/state.v | 543 +++ coq/ethereum/byzantium/transactions.ast | 106 + .../byzantium}/transactions.v | 3 +- coq/ethereum/byzantium/trie.ast | 1618 +++++++ coq/ethereum/byzantium/trie.v | 274 ++ coq/ethereum/byzantium/utils/__init__.ast | 5 + coq/ethereum/byzantium/utils/__init__.v | 4 + coq/ethereum/byzantium/utils/address.ast | 139 + coq/ethereum/byzantium/utils/address.v | 67 + coq/ethereum/byzantium/utils/hexadecimal.ast | 124 + coq/ethereum/byzantium/utils/hexadecimal.v | 68 + coq/ethereum/byzantium/utils/message.ast | 241 + coq/ethereum/byzantium/utils/message.v | 59 + coq/ethereum/byzantium/vm/__init__.ast | 509 +++ coq/ethereum/byzantium/vm/__init__.v | 63 + coq/ethereum/byzantium/vm/exceptions.ast | 155 + coq/ethereum/byzantium/vm/exceptions.v | 15 + coq/ethereum/byzantium/vm/gas.ast | 809 ++++ coq/ethereum/byzantium/vm/gas.v | 151 + .../byzantium/vm/instructions/__init__.ast | 1696 +++++++ .../byzantium/vm/instructions/__init__.v | 15 + .../byzantium/vm/instructions/arithmetic.ast | 1289 ++++++ .../byzantium/vm/instructions/arithmetic.v | 387 ++ .../byzantium/vm/instructions/bitwise.ast | 418 ++ .../byzantium/vm/instructions/bitwise.v | 156 + .../byzantium/vm/instructions/block.ast | 437 ++ .../byzantium/vm/instructions/block.v | 183 + .../byzantium/vm/instructions/comparison.ast | 514 +++ .../byzantium/vm/instructions/comparison.v | 206 + .../vm/instructions/control_flow.ast | 371 ++ .../byzantium/vm/instructions/control_flow.v | 156 + .../byzantium/vm/instructions/environment.ast | 1451 ++++++ .../byzantium/vm/instructions/environment.v | 499 ++ .../byzantium/vm/instructions/keccak.ast | 205 + .../byzantium/vm/instructions/keccak.v | 67 + .../byzantium/vm/instructions/log.ast | 323 ++ coq/ethereum/byzantium/vm/instructions/log.v | 61 + .../byzantium/vm/instructions/memory.ast | 463 ++ .../byzantium/vm/instructions/memory.v | 158 + .../byzantium/vm/instructions/stack.ast | 1083 +++++ .../byzantium/vm/instructions/stack.v | 133 + .../byzantium/vm/instructions/storage.ast | 295 ++ .../byzantium/vm/instructions/storage.v | 90 + .../byzantium/vm/instructions/system.ast | 2516 +++++++++++ .../byzantium/vm/instructions/system.v | 494 ++ coq/ethereum/byzantium/vm/interpreter.ast | 1123 +++++ coq/ethereum/byzantium/vm/interpreter.v | 155 + coq/ethereum/byzantium/vm/memory.ast | 148 + coq/ethereum/byzantium/vm/memory.v | 75 + .../vm/precompiled_contracts/__init__.ast | 89 + .../vm/precompiled_contracts/__init__.v | 16 + .../vm/precompiled_contracts/alt_bn128.ast | 913 ++++ .../vm/precompiled_contracts/alt_bn128.v | 187 + .../vm/precompiled_contracts/ecrecover.ast | 306 ++ .../vm/precompiled_contracts/ecrecover.v | 93 + .../vm/precompiled_contracts/identity.ast | 96 + .../vm/precompiled_contracts/identity.v | 36 + .../vm/precompiled_contracts/mapping.ast | 89 + .../vm/precompiled_contracts/mapping.v | 22 + .../vm/precompiled_contracts/modexp.ast | 631 +++ .../vm/precompiled_contracts/modexp.v | 202 + .../vm/precompiled_contracts/ripemd160.ast | 131 + .../vm/precompiled_contracts/ripemd160.v | 42 + .../vm/precompiled_contracts/sha256.ast | 112 + .../vm/precompiled_contracts/sha256.v | 32 + coq/ethereum/byzantium/vm/runtime.ast | 180 + coq/ethereum/byzantium/vm/runtime.v | 49 + coq/ethereum/byzantium/vm/stack.ast | 109 + coq/ethereum/byzantium/vm/stack.v | 53 + .../cancun}/__init__.ast | 0 .../cancun}/__init__.v | 0 .../cancun}/blocks.ast | 0 coq/ethereum/cancun/blocks.v | 19 + coq/ethereum/cancun/bloom.ast | 208 + coq/ethereum/cancun/bloom.v | 66 + coq/ethereum/cancun/exceptions.ast | 72 + coq/ethereum/cancun/exceptions.v | 6 + coq/{translation => ethereum/cancun}/fork.ast | 0 coq/ethereum/cancun/fork.v | 695 +++ .../cancun}/fork_types.ast | 0 coq/ethereum/cancun/fork_types.v | 29 + .../cancun}/state.ast | 0 coq/ethereum/cancun/state.v | 667 +++ .../cancun}/transactions.ast | 0 coq/ethereum/cancun/transactions.v | 27 + coq/{translation => ethereum/cancun}/trie.ast | 0 coq/ethereum/cancun/trie.v | 274 ++ coq/ethereum/cancun/utils/__init__.ast | 5 + coq/ethereum/cancun/utils/__init__.v | 4 + .../cancun}/utils/address.ast | 0 coq/ethereum/cancun/utils/address.v | 99 + .../cancun}/utils/hexadecimal.ast | 0 coq/ethereum/cancun/utils/hexadecimal.v | 68 + .../cancun}/utils/message.ast | 0 coq/ethereum/cancun/utils/message.v | 82 + .../cancun}/vm/__init__.ast | 0 coq/ethereum/cancun/vm/__init__.v | 69 + .../cancun}/vm/exceptions.ast | 0 coq/ethereum/cancun/vm/exceptions.v | 15 + .../cancun}/vm/gas.ast | 0 coq/ethereum/cancun/vm/gas.v | 251 + .../cancun}/vm/instructions/__init__.ast | 0 .../cancun/vm/instructions/__init__.v | 15 + .../cancun/vm/instructions/arithmetic.ast | 1289 ++++++ .../cancun/vm/instructions/arithmetic.v | 387 ++ .../cancun/vm/instructions/bitwise.ast | 751 +++ coq/ethereum/cancun/vm/instructions/bitwise.v | 245 + .../cancun}/vm/instructions/block.ast | 0 coq/ethereum/cancun/vm/instructions/block.v | 249 + .../cancun/vm/instructions/comparison.ast | 514 +++ .../cancun/vm/instructions/comparison.v | 206 + .../cancun/vm/instructions/control_flow.ast | 371 ++ .../cancun/vm/instructions/control_flow.v | 156 + .../cancun}/vm/instructions/environment.ast | 0 .../cancun/vm/instructions/environment.v | 623 +++ .../cancun/vm/instructions/keccak.ast | 205 + coq/ethereum/cancun/vm/instructions/keccak.v | 67 + coq/ethereum/cancun/vm/instructions/log.ast | 323 ++ coq/ethereum/cancun/vm/instructions/log.v | 61 + .../cancun}/vm/instructions/memory.ast | 0 coq/ethereum/cancun/vm/instructions/memory.v | 202 + .../cancun}/vm/instructions/stack.ast | 0 coq/ethereum/cancun/vm/instructions/stack.v | 130 + .../cancun}/vm/instructions/storage.ast | 0 coq/ethereum/cancun/vm/instructions/storage.v | 157 + .../cancun}/vm/instructions/system.ast | 0 coq/ethereum/cancun/vm/instructions/system.v | 586 +++ .../cancun}/vm/interpreter.ast | 0 coq/ethereum/cancun/vm/interpreter.v | 161 + coq/ethereum/cancun/vm/memory.ast | 148 + coq/ethereum/cancun/vm/memory.v | 75 + .../vm/precompiled_contracts/__init__.ast | 0 .../vm/precompiled_contracts/__init__.v | 16 + .../vm/precompiled_contracts/alt_bn128.ast | 913 ++++ .../vm/precompiled_contracts/alt_bn128.v | 187 + .../vm/precompiled_contracts/blake2f.ast | 137 + .../cancun/vm/precompiled_contracts/blake2f.v | 41 + .../vm/precompiled_contracts/ecrecover.ast | 306 ++ .../vm/precompiled_contracts/ecrecover.v | 93 + .../vm/precompiled_contracts/identity.ast | 96 + .../vm/precompiled_contracts/identity.v | 36 + .../vm/precompiled_contracts/mapping.ast | 0 .../cancun/vm/precompiled_contracts/mapping.v | 24 + .../vm/precompiled_contracts/modexp.ast | 638 +++ .../cancun/vm/precompiled_contracts/modexp.v | 203 + .../point_evaluation.ast | 0 .../precompiled_contracts/point_evaluation.v | 56 + .../vm/precompiled_contracts/ripemd160.ast | 131 + .../vm/precompiled_contracts/ripemd160.v | 42 + .../vm/precompiled_contracts/sha256.ast | 112 + .../cancun/vm/precompiled_contracts/sha256.v | 32 + coq/ethereum/cancun/vm/runtime.ast | 180 + coq/ethereum/cancun/vm/runtime.v | 49 + coq/ethereum/cancun/vm/stack.ast | 109 + coq/ethereum/cancun/vm/stack.v | 53 + coq/ethereum/constantinople/__init__.ast | 18 + coq/ethereum/constantinople/__init__.v | 7 + coq/ethereum/constantinople/blocks.ast | 218 + coq/ethereum/constantinople/blocks.v | 19 + coq/ethereum/constantinople/bloom.ast | 208 + coq/ethereum/constantinople/bloom.v | 66 + coq/ethereum/constantinople/fork.ast | 3186 +++++++++++++ coq/ethereum/constantinople/fork.v | 760 ++++ coq/ethereum/constantinople/fork_types.ast | 146 + coq/ethereum/constantinople/fork_types.v | 29 + coq/ethereum/constantinople/state.ast | 1500 ++++++ coq/ethereum/constantinople/state.v | 543 +++ coq/ethereum/constantinople/transactions.ast | 106 + coq/ethereum/constantinople/transactions.v | 12 + coq/ethereum/constantinople/trie.ast | 1618 +++++++ coq/ethereum/constantinople/trie.v | 274 ++ .../constantinople/utils/__init__.ast | 5 + coq/ethereum/constantinople/utils/__init__.v | 4 + coq/ethereum/constantinople/utils/address.ast | 216 + coq/ethereum/constantinople/utils/address.v | 99 + .../constantinople/utils/hexadecimal.ast | 124 + .../constantinople/utils/hexadecimal.v | 68 + coq/ethereum/constantinople/utils/message.ast | 241 + coq/ethereum/constantinople/utils/message.v | 59 + coq/ethereum/constantinople/vm/__init__.ast | 509 +++ coq/ethereum/constantinople/vm/__init__.v | 63 + coq/ethereum/constantinople/vm/exceptions.ast | 155 + coq/ethereum/constantinople/vm/exceptions.v | 15 + coq/ethereum/constantinople/vm/gas.ast | 817 ++++ coq/ethereum/constantinople/vm/gas.v | 151 + .../vm/instructions/__init__.ast | 1756 +++++++ .../constantinople/vm/instructions/__init__.v | 15 + .../vm/instructions/arithmetic.ast | 1289 ++++++ .../vm/instructions/arithmetic.v | 387 ++ .../vm/instructions/bitwise.ast | 751 +++ .../constantinople/vm/instructions/bitwise.v | 245 + .../constantinople/vm/instructions/block.ast | 437 ++ .../constantinople/vm/instructions/block.v | 183 + .../vm/instructions/comparison.ast | 514 +++ .../vm/instructions/comparison.v | 206 + .../vm/instructions/control_flow.ast | 371 ++ .../vm/instructions/control_flow.v | 156 + .../vm/instructions/environment.ast | 1571 +++++++ .../vm/instructions/environment.v | 530 +++ .../constantinople/vm/instructions/keccak.ast | 205 + .../constantinople/vm/instructions/keccak.v | 67 + .../constantinople/vm/instructions/log.ast | 323 ++ .../constantinople/vm/instructions/log.v | 61 + .../constantinople/vm/instructions/memory.ast | 463 ++ .../constantinople/vm/instructions/memory.v | 158 + .../constantinople/vm/instructions/stack.ast | 1083 +++++ .../constantinople/vm/instructions/stack.v | 133 + .../vm/instructions/storage.ast | 295 ++ .../constantinople/vm/instructions/storage.v | 90 + .../constantinople/vm/instructions/system.ast | 2745 +++++++++++ .../constantinople/vm/instructions/system.v | 581 +++ .../constantinople/vm/interpreter.ast | 1123 +++++ coq/ethereum/constantinople/vm/interpreter.v | 155 + coq/ethereum/constantinople/vm/memory.ast | 148 + coq/ethereum/constantinople/vm/memory.v | 75 + .../vm/precompiled_contracts/__init__.ast | 89 + .../vm/precompiled_contracts/__init__.v | 16 + .../vm/precompiled_contracts/alt_bn128.ast | 913 ++++ .../vm/precompiled_contracts/alt_bn128.v | 187 + .../vm/precompiled_contracts/ecrecover.ast | 306 ++ .../vm/precompiled_contracts/ecrecover.v | 93 + .../vm/precompiled_contracts/identity.ast | 96 + .../vm/precompiled_contracts/identity.v | 36 + .../vm/precompiled_contracts/mapping.ast | 89 + .../vm/precompiled_contracts/mapping.v | 22 + .../vm/precompiled_contracts/modexp.ast | 631 +++ .../vm/precompiled_contracts/modexp.v | 202 + .../vm/precompiled_contracts/ripemd160.ast | 131 + .../vm/precompiled_contracts/ripemd160.v | 42 + .../vm/precompiled_contracts/sha256.ast | 112 + .../vm/precompiled_contracts/sha256.v | 32 + coq/ethereum/constantinople/vm/runtime.ast | 180 + coq/ethereum/constantinople/vm/runtime.v | 49 + coq/ethereum/constantinople/vm/stack.ast | 109 + coq/ethereum/constantinople/vm/stack.v | 53 + coq/ethereum/crypto/__init__.ast | 5 + coq/ethereum/crypto/__init__.v | 4 + coq/ethereum/crypto/alt_bn128.ast | 1113 +++++ coq/ethereum/crypto/alt_bn128.v | 77 + coq/ethereum/crypto/blake2.ast | 1714 +++++++ coq/ethereum/crypto/blake2.v | 23 + coq/ethereum/crypto/elliptic_curve.ast | 967 ++++ coq/ethereum/crypto/elliptic_curve.v | 48 + coq/ethereum/crypto/finite_field.ast | 2896 ++++++++++++ coq/ethereum/crypto/finite_field.v | 8 + coq/ethereum/crypto/hash.ast | 121 + coq/ethereum/crypto/hash.v | 56 + coq/ethereum/crypto/kzg.ast | 696 +++ coq/ethereum/crypto/kzg.v | 129 + coq/ethereum/dao_fork/__init__.ast | 18 + coq/ethereum/dao_fork/__init__.v | 7 + coq/ethereum/dao_fork/blocks.ast | 218 + coq/ethereum/dao_fork/blocks.v | 19 + coq/ethereum/dao_fork/bloom.ast | 208 + coq/ethereum/dao_fork/bloom.v | 66 + coq/ethereum/dao_fork/dao.ast | 200 + coq/ethereum/dao_fork/dao.v | 31 + coq/ethereum/dao_fork/fork.ast | 2974 ++++++++++++ coq/ethereum/dao_fork/fork.v | 758 ++++ coq/ethereum/dao_fork/fork_types.ast | 146 + coq/ethereum/dao_fork/fork_types.v | 29 + coq/ethereum/dao_fork/state.ast | 1292 ++++++ coq/ethereum/dao_fork/state.v | 471 ++ coq/ethereum/dao_fork/transactions.ast | 106 + coq/ethereum/dao_fork/transactions.v | 12 + coq/ethereum/dao_fork/trie.ast | 1618 +++++++ coq/ethereum/dao_fork/trie.v | 274 ++ coq/ethereum/dao_fork/utils/__init__.ast | 5 + coq/ethereum/dao_fork/utils/__init__.v | 4 + coq/ethereum/dao_fork/utils/address.ast | 139 + coq/ethereum/dao_fork/utils/address.v | 66 + coq/ethereum/dao_fork/utils/hexadecimal.ast | 124 + coq/ethereum/dao_fork/utils/hexadecimal.v | 68 + coq/ethereum/dao_fork/utils/message.ast | 234 + coq/ethereum/dao_fork/utils/message.v | 55 + coq/ethereum/dao_fork/vm/__init__.ast | 362 ++ coq/ethereum/dao_fork/vm/__init__.v | 56 + coq/ethereum/dao_fork/vm/exceptions.ast | 125 + coq/ethereum/dao_fork/vm/exceptions.v | 15 + coq/ethereum/dao_fork/vm/gas.ast | 759 ++++ coq/ethereum/dao_fork/vm/gas.v | 125 + .../dao_fork/vm/instructions/__init__.ast | 1648 +++++++ .../dao_fork/vm/instructions/__init__.v | 15 + .../dao_fork/vm/instructions/arithmetic.ast | 1289 ++++++ .../dao_fork/vm/instructions/arithmetic.v | 387 ++ .../dao_fork/vm/instructions/bitwise.ast | 418 ++ .../dao_fork/vm/instructions/bitwise.v | 156 + .../dao_fork/vm/instructions/block.ast | 437 ++ coq/ethereum/dao_fork/vm/instructions/block.v | 183 + .../dao_fork/vm/instructions/comparison.ast | 514 +++ .../dao_fork/vm/instructions/comparison.v | 206 + .../dao_fork/vm/instructions/control_flow.ast | 371 ++ .../dao_fork/vm/instructions/control_flow.v | 156 + .../dao_fork/vm/instructions/environment.ast | 1199 +++++ .../dao_fork/vm/instructions/environment.v | 434 ++ .../dao_fork/vm/instructions/keccak.ast | 205 + .../dao_fork/vm/instructions/keccak.v | 67 + coq/ethereum/dao_fork/vm/instructions/log.ast | 306 ++ coq/ethereum/dao_fork/vm/instructions/log.v | 59 + .../dao_fork/vm/instructions/memory.ast | 463 ++ .../dao_fork/vm/instructions/memory.v | 158 + .../dao_fork/vm/instructions/stack.ast | 1083 +++++ coq/ethereum/dao_fork/vm/instructions/stack.v | 133 + .../dao_fork/vm/instructions/storage.ast | 278 ++ .../dao_fork/vm/instructions/storage.v | 88 + .../dao_fork/vm/instructions/system.ast | 1863 ++++++++ .../dao_fork/vm/instructions/system.v | 357 ++ coq/ethereum/dao_fork/vm/interpreter.ast | 975 ++++ coq/ethereum/dao_fork/vm/interpreter.v | 151 + coq/ethereum/dao_fork/vm/memory.ast | 148 + coq/ethereum/dao_fork/vm/memory.v | 75 + .../vm/precompiled_contracts/__init__.ast | 52 + .../vm/precompiled_contracts/__init__.v | 16 + .../vm/precompiled_contracts/ecrecover.ast | 306 ++ .../vm/precompiled_contracts/ecrecover.v | 93 + .../vm/precompiled_contracts/identity.ast | 96 + .../vm/precompiled_contracts/identity.v | 36 + .../vm/precompiled_contracts/mapping.ast | 65 + .../vm/precompiled_contracts/mapping.v | 20 + .../vm/precompiled_contracts/ripemd160.ast | 131 + .../vm/precompiled_contracts/ripemd160.v | 42 + .../vm/precompiled_contracts/sha256.ast | 112 + .../vm/precompiled_contracts/sha256.v | 32 + coq/ethereum/dao_fork/vm/runtime.ast | 180 + coq/ethereum/dao_fork/vm/runtime.v | 49 + coq/ethereum/dao_fork/vm/stack.ast | 109 + coq/ethereum/dao_fork/vm/stack.v | 53 + coq/ethereum/ethash.ast | 1355 ++++++ coq/ethereum/ethash.v | 287 ++ coq/ethereum/exceptions.ast | 59 + coq/ethereum/exceptions.v | 4 + coq/ethereum/fork_criteria.ast | 539 +++ coq/ethereum/fork_criteria.v | 26 + coq/ethereum/frontier/__init__.ast | 18 + coq/ethereum/frontier/__init__.v | 5 + coq/ethereum/frontier/blocks.ast | 218 + coq/ethereum/frontier/blocks.v | 19 + coq/ethereum/frontier/bloom.ast | 208 + coq/ethereum/frontier/bloom.v | 66 + coq/ethereum/frontier/fork.ast | 2860 ++++++++++++ coq/ethereum/frontier/fork.v | 736 +++ coq/ethereum/frontier/fork_types.ast | 146 + coq/ethereum/frontier/fork_types.v | 29 + coq/ethereum/frontier/state.ast | 1292 ++++++ coq/ethereum/frontier/state.v | 471 ++ coq/ethereum/frontier/transactions.ast | 102 + coq/ethereum/frontier/transactions.v | 12 + coq/ethereum/frontier/trie.ast | 1619 +++++++ coq/ethereum/frontier/trie.v | 274 ++ coq/ethereum/frontier/utils/__init__.ast | 5 + coq/ethereum/frontier/utils/__init__.v | 4 + coq/ethereum/frontier/utils/address.ast | 139 + coq/ethereum/frontier/utils/address.v | 66 + coq/ethereum/frontier/utils/hexadecimal.ast | 124 + coq/ethereum/frontier/utils/hexadecimal.v | 68 + coq/ethereum/frontier/utils/message.ast | 227 + coq/ethereum/frontier/utils/message.v | 53 + coq/ethereum/frontier/vm/__init__.ast | 358 ++ coq/ethereum/frontier/vm/__init__.v | 56 + coq/ethereum/frontier/vm/exceptions.ast | 125 + coq/ethereum/frontier/vm/exceptions.v | 15 + coq/ethereum/frontier/vm/gas.ast | 759 ++++ coq/ethereum/frontier/vm/gas.v | 125 + .../frontier/vm/instructions/__init__.ast | 1636 +++++++ .../frontier/vm/instructions/__init__.v | 15 + .../frontier/vm/instructions/arithmetic.ast | 1289 ++++++ .../frontier/vm/instructions/arithmetic.v | 387 ++ .../frontier/vm/instructions/bitwise.ast | 418 ++ .../frontier/vm/instructions/bitwise.v | 156 + .../frontier/vm/instructions/block.ast | 437 ++ coq/ethereum/frontier/vm/instructions/block.v | 183 + .../frontier/vm/instructions/comparison.ast | 514 +++ .../frontier/vm/instructions/comparison.v | 206 + .../frontier/vm/instructions/control_flow.ast | 371 ++ .../frontier/vm/instructions/control_flow.v | 156 + .../frontier/vm/instructions/environment.ast | 1199 +++++ .../frontier/vm/instructions/environment.v | 434 ++ .../frontier/vm/instructions/keccak.ast | 205 + .../frontier/vm/instructions/keccak.v | 67 + coq/ethereum/frontier/vm/instructions/log.ast | 306 ++ coq/ethereum/frontier/vm/instructions/log.v | 59 + .../frontier/vm/instructions/memory.ast | 463 ++ .../frontier/vm/instructions/memory.v | 158 + .../frontier/vm/instructions/stack.ast | 1083 +++++ coq/ethereum/frontier/vm/instructions/stack.v | 133 + .../frontier/vm/instructions/storage.ast | 278 ++ .../frontier/vm/instructions/storage.v | 88 + .../frontier/vm/instructions/system.ast | 1663 +++++++ .../frontier/vm/instructions/system.v | 301 ++ coq/ethereum/frontier/vm/interpreter.ast | 947 ++++ coq/ethereum/frontier/vm/interpreter.v | 151 + coq/ethereum/frontier/vm/memory.ast | 148 + coq/ethereum/frontier/vm/memory.v | 75 + .../vm/precompiled_contracts/__init__.ast | 52 + .../vm/precompiled_contracts/__init__.v | 16 + .../vm/precompiled_contracts/ecrecover.ast | 306 ++ .../vm/precompiled_contracts/ecrecover.v | 93 + .../vm/precompiled_contracts/identity.ast | 96 + .../vm/precompiled_contracts/identity.v | 36 + .../vm/precompiled_contracts/mapping.ast | 65 + .../vm/precompiled_contracts/mapping.v | 20 + .../vm/precompiled_contracts/ripemd160.ast | 131 + .../vm/precompiled_contracts/ripemd160.v | 42 + .../vm/precompiled_contracts/sha256.ast | 112 + .../vm/precompiled_contracts/sha256.v | 32 + coq/ethereum/frontier/vm/runtime.ast | 180 + coq/ethereum/frontier/vm/runtime.v | 49 + coq/ethereum/frontier/vm/stack.ast | 109 + coq/ethereum/frontier/vm/stack.v | 53 + coq/ethereum/genesis.ast | 1107 +++++ coq/ethereum/genesis.v | 104 + coq/ethereum/gray_glacier/__init__.ast | 18 + coq/ethereum/gray_glacier/__init__.v | 6 + coq/ethereum/gray_glacier/blocks.ast | 230 + coq/ethereum/gray_glacier/blocks.v | 19 + coq/ethereum/gray_glacier/bloom.ast | 208 + coq/ethereum/gray_glacier/bloom.v | 66 + coq/ethereum/gray_glacier/exceptions.ast | 72 + coq/ethereum/gray_glacier/exceptions.v | 6 + coq/ethereum/gray_glacier/fork.ast | 3991 ++++++++++++++++ coq/ethereum/gray_glacier/fork.v | 847 ++++ coq/ethereum/gray_glacier/fork_types.ast | 146 + coq/ethereum/gray_glacier/fork_types.v | 29 + coq/ethereum/gray_glacier/state.ast | 1692 +++++++ coq/ethereum/gray_glacier/state.v | 593 +++ coq/ethereum/gray_glacier/transactions.ast | 492 ++ coq/ethereum/gray_glacier/transactions.v | 27 + coq/ethereum/gray_glacier/trie.ast | 1632 +++++++ coq/ethereum/gray_glacier/trie.v | 274 ++ coq/ethereum/gray_glacier/utils/__init__.ast | 5 + coq/ethereum/gray_glacier/utils/__init__.v | 4 + coq/ethereum/gray_glacier/utils/address.ast | 216 + coq/ethereum/gray_glacier/utils/address.v | 99 + .../gray_glacier/utils/hexadecimal.ast | 124 + coq/ethereum/gray_glacier/utils/hexadecimal.v | 68 + coq/ethereum/gray_glacier/utils/message.ast | 335 ++ coq/ethereum/gray_glacier/utils/message.v | 82 + coq/ethereum/gray_glacier/vm/__init__.ast | 591 +++ coq/ethereum/gray_glacier/vm/__init__.v | 69 + coq/ethereum/gray_glacier/vm/exceptions.ast | 175 + coq/ethereum/gray_glacier/vm/exceptions.v | 15 + coq/ethereum/gray_glacier/vm/gas.ast | 813 ++++ coq/ethereum/gray_glacier/vm/gas.v | 151 + .../gray_glacier/vm/instructions/__init__.ast | 1792 ++++++++ .../gray_glacier/vm/instructions/__init__.v | 15 + .../vm/instructions/arithmetic.ast | 1289 ++++++ .../gray_glacier/vm/instructions/arithmetic.v | 387 ++ .../gray_glacier/vm/instructions/bitwise.ast | 751 +++ .../gray_glacier/vm/instructions/bitwise.v | 245 + .../gray_glacier/vm/instructions/block.ast | 492 ++ .../gray_glacier/vm/instructions/block.v | 207 + .../vm/instructions/comparison.ast | 514 +++ .../gray_glacier/vm/instructions/comparison.v | 206 + .../vm/instructions/control_flow.ast | 371 ++ .../vm/instructions/control_flow.v | 156 + .../vm/instructions/environment.ast | 1828 ++++++++ .../vm/instructions/environment.v | 568 +++ .../gray_glacier/vm/instructions/keccak.ast | 205 + .../gray_glacier/vm/instructions/keccak.v | 67 + .../gray_glacier/vm/instructions/log.ast | 323 ++ .../gray_glacier/vm/instructions/log.v | 61 + .../gray_glacier/vm/instructions/memory.ast | 463 ++ .../gray_glacier/vm/instructions/memory.v | 158 + .../gray_glacier/vm/instructions/stack.ast | 1083 +++++ .../gray_glacier/vm/instructions/stack.v | 133 + .../gray_glacier/vm/instructions/storage.ast | 551 +++ .../gray_glacier/vm/instructions/storage.v | 97 + .../gray_glacier/vm/instructions/system.ast | 2897 ++++++++++++ .../gray_glacier/vm/instructions/system.v | 585 +++ coq/ethereum/gray_glacier/vm/interpreter.ast | 1177 +++++ coq/ethereum/gray_glacier/vm/interpreter.v | 159 + coq/ethereum/gray_glacier/vm/memory.ast | 148 + coq/ethereum/gray_glacier/vm/memory.v | 75 + .../vm/precompiled_contracts/__init__.ast | 97 + .../vm/precompiled_contracts/__init__.v | 16 + .../vm/precompiled_contracts/alt_bn128.ast | 913 ++++ .../vm/precompiled_contracts/alt_bn128.v | 187 + .../vm/precompiled_contracts/blake2f.ast | 137 + .../vm/precompiled_contracts/blake2f.v | 41 + .../vm/precompiled_contracts/ecrecover.ast | 306 ++ .../vm/precompiled_contracts/ecrecover.v | 93 + .../vm/precompiled_contracts/identity.ast | 96 + .../vm/precompiled_contracts/identity.v | 36 + .../vm/precompiled_contracts/mapping.ast | 97 + .../vm/precompiled_contracts/mapping.v | 23 + .../vm/precompiled_contracts/modexp.ast | 638 +++ .../vm/precompiled_contracts/modexp.v | 203 + .../vm/precompiled_contracts/ripemd160.ast | 131 + .../vm/precompiled_contracts/ripemd160.v | 42 + .../vm/precompiled_contracts/sha256.ast | 112 + .../vm/precompiled_contracts/sha256.v | 32 + coq/ethereum/gray_glacier/vm/runtime.ast | 180 + coq/ethereum/gray_glacier/vm/runtime.v | 49 + coq/ethereum/gray_glacier/vm/stack.ast | 109 + coq/ethereum/gray_glacier/vm/stack.v | 53 + coq/ethereum/homestead/__init__.ast | 18 + coq/ethereum/homestead/__init__.v | 8 + coq/ethereum/homestead/blocks.ast | 218 + coq/ethereum/homestead/blocks.v | 19 + coq/ethereum/homestead/bloom.ast | 208 + coq/ethereum/homestead/bloom.v | 66 + coq/ethereum/homestead/fork.ast | 2908 ++++++++++++ coq/ethereum/homestead/fork.v | 744 +++ coq/ethereum/homestead/fork_types.ast | 146 + coq/ethereum/homestead/fork_types.v | 29 + coq/ethereum/homestead/state.ast | 1292 ++++++ coq/ethereum/homestead/state.v | 471 ++ coq/ethereum/homestead/transactions.ast | 106 + coq/ethereum/homestead/transactions.v | 12 + coq/ethereum/homestead/trie.ast | 1618 +++++++ coq/ethereum/homestead/trie.v | 274 ++ coq/ethereum/homestead/utils/__init__.ast | 5 + coq/ethereum/homestead/utils/__init__.v | 4 + coq/ethereum/homestead/utils/address.ast | 139 + coq/ethereum/homestead/utils/address.v | 66 + coq/ethereum/homestead/utils/hexadecimal.ast | 124 + coq/ethereum/homestead/utils/hexadecimal.v | 68 + coq/ethereum/homestead/utils/message.ast | 234 + coq/ethereum/homestead/utils/message.v | 55 + coq/ethereum/homestead/vm/__init__.ast | 362 ++ coq/ethereum/homestead/vm/__init__.v | 56 + coq/ethereum/homestead/vm/exceptions.ast | 125 + coq/ethereum/homestead/vm/exceptions.v | 15 + coq/ethereum/homestead/vm/gas.ast | 759 ++++ coq/ethereum/homestead/vm/gas.v | 125 + .../homestead/vm/instructions/__init__.ast | 1648 +++++++ .../homestead/vm/instructions/__init__.v | 15 + .../homestead/vm/instructions/arithmetic.ast | 1289 ++++++ .../homestead/vm/instructions/arithmetic.v | 387 ++ .../homestead/vm/instructions/bitwise.ast | 418 ++ .../homestead/vm/instructions/bitwise.v | 156 + .../homestead/vm/instructions/block.ast | 437 ++ .../homestead/vm/instructions/block.v | 183 + .../homestead/vm/instructions/comparison.ast | 514 +++ .../homestead/vm/instructions/comparison.v | 206 + .../vm/instructions/control_flow.ast | 371 ++ .../homestead/vm/instructions/control_flow.v | 156 + .../homestead/vm/instructions/environment.ast | 1199 +++++ .../homestead/vm/instructions/environment.v | 434 ++ .../homestead/vm/instructions/keccak.ast | 205 + .../homestead/vm/instructions/keccak.v | 67 + .../homestead/vm/instructions/log.ast | 306 ++ coq/ethereum/homestead/vm/instructions/log.v | 59 + .../homestead/vm/instructions/memory.ast | 463 ++ .../homestead/vm/instructions/memory.v | 158 + .../homestead/vm/instructions/stack.ast | 1083 +++++ .../homestead/vm/instructions/stack.v | 133 + .../homestead/vm/instructions/storage.ast | 278 ++ .../homestead/vm/instructions/storage.v | 88 + .../homestead/vm/instructions/system.ast | 1863 ++++++++ .../homestead/vm/instructions/system.v | 357 ++ coq/ethereum/homestead/vm/interpreter.ast | 975 ++++ coq/ethereum/homestead/vm/interpreter.v | 151 + coq/ethereum/homestead/vm/memory.ast | 148 + coq/ethereum/homestead/vm/memory.v | 75 + .../vm/precompiled_contracts/__init__.ast | 52 + .../vm/precompiled_contracts/__init__.v | 16 + .../vm/precompiled_contracts/ecrecover.ast | 306 ++ .../vm/precompiled_contracts/ecrecover.v | 93 + .../vm/precompiled_contracts/identity.ast | 96 + .../vm/precompiled_contracts/identity.v | 36 + .../vm/precompiled_contracts/mapping.ast | 65 + .../vm/precompiled_contracts/mapping.v | 20 + .../vm/precompiled_contracts/ripemd160.ast | 131 + .../vm/precompiled_contracts/ripemd160.v | 42 + .../vm/precompiled_contracts/sha256.ast | 112 + .../vm/precompiled_contracts/sha256.v | 32 + coq/ethereum/homestead/vm/runtime.ast | 180 + coq/ethereum/homestead/vm/runtime.v | 49 + coq/ethereum/homestead/vm/stack.ast | 109 + coq/ethereum/homestead/vm/stack.v | 53 + coq/ethereum/istanbul/__init__.ast | 18 + coq/ethereum/istanbul/__init__.v | 7 + coq/ethereum/istanbul/blocks.ast | 218 + coq/ethereum/istanbul/blocks.v | 19 + coq/ethereum/istanbul/bloom.ast | 208 + coq/ethereum/istanbul/bloom.v | 66 + coq/ethereum/istanbul/fork.ast | 3189 +++++++++++++ coq/ethereum/istanbul/fork.v | 760 ++++ coq/ethereum/istanbul/fork_types.ast | 146 + coq/ethereum/istanbul/fork_types.v | 29 + coq/ethereum/istanbul/state.ast | 1692 +++++++ coq/ethereum/istanbul/state.v | 593 +++ coq/ethereum/istanbul/transactions.ast | 106 + coq/ethereum/istanbul/transactions.v | 12 + coq/ethereum/istanbul/trie.ast | 1618 +++++++ coq/ethereum/istanbul/trie.v | 274 ++ coq/ethereum/istanbul/utils/__init__.ast | 5 + coq/ethereum/istanbul/utils/__init__.v | 4 + coq/ethereum/istanbul/utils/address.ast | 216 + coq/ethereum/istanbul/utils/address.v | 99 + coq/ethereum/istanbul/utils/hexadecimal.ast | 124 + coq/ethereum/istanbul/utils/hexadecimal.v | 68 + coq/ethereum/istanbul/utils/message.ast | 241 + coq/ethereum/istanbul/utils/message.v | 59 + coq/ethereum/istanbul/vm/__init__.ast | 514 +++ coq/ethereum/istanbul/vm/__init__.v | 63 + coq/ethereum/istanbul/vm/exceptions.ast | 165 + coq/ethereum/istanbul/vm/exceptions.v | 15 + coq/ethereum/istanbul/vm/gas.ast | 833 ++++ coq/ethereum/istanbul/vm/gas.v | 151 + .../istanbul/vm/instructions/__init__.ast | 1780 ++++++++ .../istanbul/vm/instructions/__init__.v | 15 + .../istanbul/vm/instructions/arithmetic.ast | 1289 ++++++ .../istanbul/vm/instructions/arithmetic.v | 387 ++ .../istanbul/vm/instructions/bitwise.ast | 751 +++ .../istanbul/vm/instructions/bitwise.v | 245 + .../istanbul/vm/instructions/block.ast | 492 ++ coq/ethereum/istanbul/vm/instructions/block.v | 207 + .../istanbul/vm/instructions/comparison.ast | 514 +++ .../istanbul/vm/instructions/comparison.v | 206 + .../istanbul/vm/instructions/control_flow.ast | 371 ++ .../istanbul/vm/instructions/control_flow.v | 156 + .../istanbul/vm/instructions/environment.ast | 1641 +++++++ .../istanbul/vm/instructions/environment.v | 556 +++ .../istanbul/vm/instructions/keccak.ast | 205 + .../istanbul/vm/instructions/keccak.v | 67 + coq/ethereum/istanbul/vm/instructions/log.ast | 323 ++ coq/ethereum/istanbul/vm/instructions/log.v | 61 + .../istanbul/vm/instructions/memory.ast | 463 ++ .../istanbul/vm/instructions/memory.v | 158 + .../istanbul/vm/instructions/stack.ast | 1083 +++++ coq/ethereum/istanbul/vm/instructions/stack.v | 133 + .../istanbul/vm/instructions/storage.ast | 437 ++ .../istanbul/vm/instructions/storage.v | 96 + .../istanbul/vm/instructions/system.ast | 2745 +++++++++++ .../istanbul/vm/instructions/system.v | 581 +++ coq/ethereum/istanbul/vm/interpreter.ast | 1137 +++++ coq/ethereum/istanbul/vm/interpreter.v | 159 + coq/ethereum/istanbul/vm/memory.ast | 148 + coq/ethereum/istanbul/vm/memory.v | 75 + .../vm/precompiled_contracts/__init__.ast | 97 + .../vm/precompiled_contracts/__init__.v | 16 + .../vm/precompiled_contracts/alt_bn128.ast | 913 ++++ .../vm/precompiled_contracts/alt_bn128.v | 187 + .../vm/precompiled_contracts/blake2f.ast | 137 + .../vm/precompiled_contracts/blake2f.v | 41 + .../vm/precompiled_contracts/ecrecover.ast | 306 ++ .../vm/precompiled_contracts/ecrecover.v | 93 + .../vm/precompiled_contracts/identity.ast | 96 + .../vm/precompiled_contracts/identity.v | 36 + .../vm/precompiled_contracts/mapping.ast | 97 + .../vm/precompiled_contracts/mapping.v | 23 + .../vm/precompiled_contracts/modexp.ast | 631 +++ .../vm/precompiled_contracts/modexp.v | 202 + .../vm/precompiled_contracts/ripemd160.ast | 131 + .../vm/precompiled_contracts/ripemd160.v | 42 + .../vm/precompiled_contracts/sha256.ast | 112 + .../vm/precompiled_contracts/sha256.v | 32 + coq/ethereum/istanbul/vm/runtime.ast | 180 + coq/ethereum/istanbul/vm/runtime.v | 49 + coq/ethereum/istanbul/vm/stack.ast | 109 + coq/ethereum/istanbul/vm/stack.v | 53 + coq/ethereum/london/__init__.ast | 18 + coq/ethereum/london/__init__.v | 6 + coq/ethereum/london/blocks.ast | 230 + coq/ethereum/london/blocks.v | 19 + coq/ethereum/london/bloom.ast | 208 + coq/ethereum/london/bloom.v | 66 + coq/ethereum/london/exceptions.ast | 72 + coq/ethereum/london/exceptions.v | 6 + coq/ethereum/london/fork.ast | 4019 +++++++++++++++++ coq/ethereum/london/fork.v | 843 ++++ coq/ethereum/london/fork_types.ast | 146 + coq/ethereum/london/fork_types.v | 29 + coq/ethereum/london/state.ast | 1692 +++++++ coq/ethereum/london/state.v | 593 +++ coq/ethereum/london/transactions.ast | 492 ++ coq/ethereum/london/transactions.v | 27 + coq/ethereum/london/trie.ast | 1632 +++++++ coq/ethereum/london/trie.v | 274 ++ coq/ethereum/london/utils/__init__.ast | 5 + coq/ethereum/london/utils/__init__.v | 4 + coq/ethereum/london/utils/address.ast | 216 + coq/ethereum/london/utils/address.v | 99 + coq/ethereum/london/utils/hexadecimal.ast | 124 + coq/ethereum/london/utils/hexadecimal.v | 68 + coq/ethereum/london/utils/message.ast | 335 ++ coq/ethereum/london/utils/message.v | 82 + coq/ethereum/london/vm/__init__.ast | 591 +++ coq/ethereum/london/vm/__init__.v | 69 + coq/ethereum/london/vm/exceptions.ast | 175 + coq/ethereum/london/vm/exceptions.v | 15 + coq/ethereum/london/vm/gas.ast | 813 ++++ coq/ethereum/london/vm/gas.v | 151 + .../london/vm/instructions/__init__.ast | 1792 ++++++++ .../london/vm/instructions/__init__.v | 15 + .../london/vm/instructions/arithmetic.ast | 1289 ++++++ .../london/vm/instructions/arithmetic.v | 387 ++ .../london/vm/instructions/bitwise.ast | 751 +++ coq/ethereum/london/vm/instructions/bitwise.v | 245 + coq/ethereum/london/vm/instructions/block.ast | 492 ++ coq/ethereum/london/vm/instructions/block.v | 207 + .../london/vm/instructions/comparison.ast | 514 +++ .../london/vm/instructions/comparison.v | 206 + .../london/vm/instructions/control_flow.ast | 371 ++ .../london/vm/instructions/control_flow.v | 156 + .../london/vm/instructions/environment.ast | 1828 ++++++++ .../london/vm/instructions/environment.v | 568 +++ .../london/vm/instructions/keccak.ast | 205 + coq/ethereum/london/vm/instructions/keccak.v | 67 + coq/ethereum/london/vm/instructions/log.ast | 323 ++ coq/ethereum/london/vm/instructions/log.v | 61 + .../london/vm/instructions/memory.ast | 463 ++ coq/ethereum/london/vm/instructions/memory.v | 158 + coq/ethereum/london/vm/instructions/stack.ast | 1083 +++++ coq/ethereum/london/vm/instructions/stack.v | 133 + .../london/vm/instructions/storage.ast | 551 +++ coq/ethereum/london/vm/instructions/storage.v | 97 + .../london/vm/instructions/system.ast | 2897 ++++++++++++ coq/ethereum/london/vm/instructions/system.v | 585 +++ coq/ethereum/london/vm/interpreter.ast | 1177 +++++ coq/ethereum/london/vm/interpreter.v | 159 + coq/ethereum/london/vm/memory.ast | 148 + coq/ethereum/london/vm/memory.v | 75 + .../vm/precompiled_contracts/__init__.ast | 97 + .../vm/precompiled_contracts/__init__.v | 16 + .../vm/precompiled_contracts/alt_bn128.ast | 913 ++++ .../vm/precompiled_contracts/alt_bn128.v | 187 + .../vm/precompiled_contracts/blake2f.ast | 137 + .../london/vm/precompiled_contracts/blake2f.v | 41 + .../vm/precompiled_contracts/ecrecover.ast | 306 ++ .../vm/precompiled_contracts/ecrecover.v | 93 + .../vm/precompiled_contracts/identity.ast | 96 + .../vm/precompiled_contracts/identity.v | 36 + .../vm/precompiled_contracts/mapping.ast | 97 + .../london/vm/precompiled_contracts/mapping.v | 23 + .../vm/precompiled_contracts/modexp.ast | 638 +++ .../london/vm/precompiled_contracts/modexp.v | 203 + .../vm/precompiled_contracts/ripemd160.ast | 131 + .../vm/precompiled_contracts/ripemd160.v | 42 + .../vm/precompiled_contracts/sha256.ast | 112 + .../london/vm/precompiled_contracts/sha256.v | 32 + coq/ethereum/london/vm/runtime.ast | 180 + coq/ethereum/london/vm/runtime.v | 49 + coq/ethereum/london/vm/stack.ast | 109 + coq/ethereum/london/vm/stack.v | 53 + coq/ethereum/muir_glacier/__init__.ast | 18 + coq/ethereum/muir_glacier/__init__.v | 6 + coq/ethereum/muir_glacier/blocks.ast | 218 + coq/ethereum/muir_glacier/blocks.v | 19 + coq/ethereum/muir_glacier/bloom.ast | 208 + coq/ethereum/muir_glacier/bloom.v | 66 + coq/ethereum/muir_glacier/fork.ast | 3189 +++++++++++++ coq/ethereum/muir_glacier/fork.v | 760 ++++ coq/ethereum/muir_glacier/fork_types.ast | 146 + coq/ethereum/muir_glacier/fork_types.v | 29 + coq/ethereum/muir_glacier/state.ast | 1692 +++++++ coq/ethereum/muir_glacier/state.v | 593 +++ coq/ethereum/muir_glacier/transactions.ast | 106 + coq/ethereum/muir_glacier/transactions.v | 12 + coq/ethereum/muir_glacier/trie.ast | 1618 +++++++ coq/ethereum/muir_glacier/trie.v | 274 ++ coq/ethereum/muir_glacier/utils/__init__.ast | 5 + coq/ethereum/muir_glacier/utils/__init__.v | 4 + coq/ethereum/muir_glacier/utils/address.ast | 216 + coq/ethereum/muir_glacier/utils/address.v | 99 + .../muir_glacier/utils/hexadecimal.ast | 124 + coq/ethereum/muir_glacier/utils/hexadecimal.v | 68 + coq/ethereum/muir_glacier/utils/message.ast | 241 + coq/ethereum/muir_glacier/utils/message.v | 59 + coq/ethereum/muir_glacier/vm/__init__.ast | 514 +++ coq/ethereum/muir_glacier/vm/__init__.v | 63 + coq/ethereum/muir_glacier/vm/exceptions.ast | 165 + coq/ethereum/muir_glacier/vm/exceptions.v | 15 + coq/ethereum/muir_glacier/vm/gas.ast | 833 ++++ coq/ethereum/muir_glacier/vm/gas.v | 151 + .../muir_glacier/vm/instructions/__init__.ast | 1780 ++++++++ .../muir_glacier/vm/instructions/__init__.v | 15 + .../vm/instructions/arithmetic.ast | 1289 ++++++ .../muir_glacier/vm/instructions/arithmetic.v | 387 ++ .../muir_glacier/vm/instructions/bitwise.ast | 751 +++ .../muir_glacier/vm/instructions/bitwise.v | 245 + .../muir_glacier/vm/instructions/block.ast | 492 ++ .../muir_glacier/vm/instructions/block.v | 207 + .../vm/instructions/comparison.ast | 514 +++ .../muir_glacier/vm/instructions/comparison.v | 206 + .../vm/instructions/control_flow.ast | 371 ++ .../vm/instructions/control_flow.v | 156 + .../vm/instructions/environment.ast | 1641 +++++++ .../vm/instructions/environment.v | 556 +++ .../muir_glacier/vm/instructions/keccak.ast | 205 + .../muir_glacier/vm/instructions/keccak.v | 67 + .../muir_glacier/vm/instructions/log.ast | 323 ++ .../muir_glacier/vm/instructions/log.v | 61 + .../muir_glacier/vm/instructions/memory.ast | 463 ++ .../muir_glacier/vm/instructions/memory.v | 158 + .../muir_glacier/vm/instructions/stack.ast | 1083 +++++ .../muir_glacier/vm/instructions/stack.v | 133 + .../muir_glacier/vm/instructions/storage.ast | 437 ++ .../muir_glacier/vm/instructions/storage.v | 96 + .../muir_glacier/vm/instructions/system.ast | 2745 +++++++++++ .../muir_glacier/vm/instructions/system.v | 581 +++ coq/ethereum/muir_glacier/vm/interpreter.ast | 1137 +++++ coq/ethereum/muir_glacier/vm/interpreter.v | 159 + coq/ethereum/muir_glacier/vm/memory.ast | 148 + coq/ethereum/muir_glacier/vm/memory.v | 75 + .../vm/precompiled_contracts/__init__.ast | 97 + .../vm/precompiled_contracts/__init__.v | 16 + .../vm/precompiled_contracts/alt_bn128.ast | 913 ++++ .../vm/precompiled_contracts/alt_bn128.v | 187 + .../vm/precompiled_contracts/blake2f.ast | 137 + .../vm/precompiled_contracts/blake2f.v | 41 + .../vm/precompiled_contracts/ecrecover.ast | 306 ++ .../vm/precompiled_contracts/ecrecover.v | 93 + .../vm/precompiled_contracts/identity.ast | 96 + .../vm/precompiled_contracts/identity.v | 36 + .../vm/precompiled_contracts/mapping.ast | 97 + .../vm/precompiled_contracts/mapping.v | 23 + .../vm/precompiled_contracts/modexp.ast | 631 +++ .../vm/precompiled_contracts/modexp.v | 202 + .../vm/precompiled_contracts/ripemd160.ast | 131 + .../vm/precompiled_contracts/ripemd160.v | 42 + .../vm/precompiled_contracts/sha256.ast | 112 + .../vm/precompiled_contracts/sha256.v | 32 + coq/ethereum/muir_glacier/vm/runtime.ast | 180 + coq/ethereum/muir_glacier/vm/runtime.v | 49 + coq/ethereum/muir_glacier/vm/stack.ast | 109 + coq/ethereum/muir_glacier/vm/stack.v | 53 + coq/ethereum/paris/__init__.ast | 18 + coq/ethereum/paris/__init__.v | 10 + coq/ethereum/paris/blocks.ast | 230 + coq/{translation => ethereum/paris}/blocks.v | 6 +- coq/ethereum/paris/bloom.ast | 208 + coq/ethereum/paris/bloom.v | 66 + coq/ethereum/paris/exceptions.ast | 72 + coq/ethereum/paris/exceptions.v | 6 + coq/ethereum/paris/fork.ast | 3032 +++++++++++++ coq/ethereum/paris/fork.v | 647 +++ coq/ethereum/paris/fork_types.ast | 146 + coq/ethereum/paris/fork_types.v | 29 + coq/ethereum/paris/state.ast | 1641 +++++++ coq/ethereum/paris/state.v | 572 +++ coq/ethereum/paris/transactions.ast | 492 ++ coq/ethereum/paris/transactions.v | 27 + coq/ethereum/paris/trie.ast | 1632 +++++++ coq/ethereum/paris/trie.v | 274 ++ coq/ethereum/paris/utils/__init__.ast | 5 + coq/ethereum/paris/utils/__init__.v | 4 + coq/ethereum/paris/utils/address.ast | 216 + coq/ethereum/paris/utils/address.v | 99 + coq/ethereum/paris/utils/hexadecimal.ast | 124 + coq/ethereum/paris/utils/hexadecimal.v | 68 + coq/ethereum/paris/utils/message.ast | 335 ++ coq/ethereum/paris/utils/message.v | 82 + coq/ethereum/paris/vm/__init__.ast | 591 +++ coq/ethereum/paris/vm/__init__.v | 69 + coq/ethereum/paris/vm/exceptions.ast | 175 + coq/ethereum/paris/vm/exceptions.v | 15 + coq/ethereum/paris/vm/gas.ast | 813 ++++ coq/ethereum/paris/vm/gas.v | 151 + .../paris/vm/instructions/__init__.ast | 1792 ++++++++ coq/ethereum/paris/vm/instructions/__init__.v | 15 + .../paris/vm/instructions/arithmetic.ast | 1289 ++++++ .../paris/vm/instructions/arithmetic.v | 387 ++ .../paris/vm/instructions/bitwise.ast | 751 +++ coq/ethereum/paris/vm/instructions/bitwise.v | 245 + coq/ethereum/paris/vm/instructions/block.ast | 495 ++ coq/ethereum/paris/vm/instructions/block.v | 249 + .../paris/vm/instructions/comparison.ast | 514 +++ .../paris/vm/instructions/comparison.v | 206 + .../paris/vm/instructions/control_flow.ast | 371 ++ .../paris/vm/instructions/control_flow.v | 156 + .../paris/vm/instructions/environment.ast | 1828 ++++++++ .../paris/vm/instructions/environment.v | 568 +++ coq/ethereum/paris/vm/instructions/keccak.ast | 205 + coq/ethereum/paris/vm/instructions/keccak.v | 67 + coq/ethereum/paris/vm/instructions/log.ast | 323 ++ coq/ethereum/paris/vm/instructions/log.v | 61 + coq/ethereum/paris/vm/instructions/memory.ast | 463 ++ coq/ethereum/paris/vm/instructions/memory.v | 158 + coq/ethereum/paris/vm/instructions/stack.ast | 1083 +++++ coq/ethereum/paris/vm/instructions/stack.v | 133 + .../paris/vm/instructions/storage.ast | 551 +++ coq/ethereum/paris/vm/instructions/storage.v | 97 + coq/ethereum/paris/vm/instructions/system.ast | 2897 ++++++++++++ coq/ethereum/paris/vm/instructions/system.v | 585 +++ coq/ethereum/paris/vm/interpreter.ast | 1188 +++++ coq/ethereum/paris/vm/interpreter.v | 159 + coq/ethereum/paris/vm/memory.ast | 148 + coq/ethereum/paris/vm/memory.v | 75 + .../vm/precompiled_contracts/__init__.ast | 97 + .../vm/precompiled_contracts/__init__.v | 2 +- .../vm/precompiled_contracts/alt_bn128.ast | 913 ++++ .../vm/precompiled_contracts/alt_bn128.v | 187 + .../vm/precompiled_contracts/blake2f.ast | 137 + .../paris/vm/precompiled_contracts/blake2f.v | 41 + .../vm/precompiled_contracts/ecrecover.ast | 306 ++ .../vm/precompiled_contracts/ecrecover.v | 93 + .../vm/precompiled_contracts/identity.ast | 96 + .../paris/vm/precompiled_contracts/identity.v | 36 + .../vm/precompiled_contracts/mapping.ast | 97 + .../paris/vm/precompiled_contracts/mapping.v | 23 + .../paris/vm/precompiled_contracts/modexp.ast | 638 +++ .../paris/vm/precompiled_contracts/modexp.v | 203 + .../vm/precompiled_contracts/ripemd160.ast | 131 + .../vm/precompiled_contracts/ripemd160.v | 42 + .../paris/vm/precompiled_contracts/sha256.ast | 112 + .../paris/vm/precompiled_contracts/sha256.v | 32 + coq/ethereum/paris/vm/runtime.ast | 180 + coq/ethereum/paris/vm/runtime.v | 49 + coq/ethereum/paris/vm/stack.ast | 109 + coq/ethereum/paris/vm/stack.v | 53 + coq/ethereum/rlp.ast | 2259 +++++++++ coq/ethereum/rlp.v | 322 ++ coq/ethereum/shanghai/__init__.ast | 18 + coq/ethereum/shanghai/__init__.v | 7 + coq/ethereum/shanghai/blocks.ast | 272 ++ coq/ethereum/shanghai/blocks.v | 19 + coq/ethereum/shanghai/bloom.ast | 208 + coq/ethereum/shanghai/bloom.v | 66 + coq/ethereum/shanghai/exceptions.ast | 72 + coq/ethereum/shanghai/exceptions.v | 6 + coq/ethereum/shanghai/fork.ast | 3253 +++++++++++++ coq/ethereum/shanghai/fork.v | 658 +++ coq/ethereum/shanghai/fork_types.ast | 146 + coq/ethereum/shanghai/fork_types.v | 29 + coq/ethereum/shanghai/state.ast | 1710 +++++++ coq/ethereum/shanghai/state.v | 585 +++ coq/ethereum/shanghai/transactions.ast | 492 ++ coq/ethereum/shanghai/transactions.v | 27 + coq/ethereum/shanghai/trie.ast | 1646 +++++++ coq/ethereum/shanghai/trie.v | 274 ++ coq/ethereum/shanghai/utils/__init__.ast | 5 + coq/ethereum/shanghai/utils/__init__.v | 4 + coq/ethereum/shanghai/utils/address.ast | 216 + coq/ethereum/shanghai/utils/address.v | 99 + coq/ethereum/shanghai/utils/hexadecimal.ast | 124 + coq/ethereum/shanghai/utils/hexadecimal.v | 68 + coq/ethereum/shanghai/utils/message.ast | 335 ++ coq/ethereum/shanghai/utils/message.v | 82 + coq/ethereum/shanghai/vm/__init__.ast | 591 +++ coq/ethereum/shanghai/vm/__init__.v | 69 + coq/ethereum/shanghai/vm/exceptions.ast | 175 + coq/ethereum/shanghai/vm/exceptions.v | 15 + coq/ethereum/shanghai/vm/gas.ast | 853 ++++ coq/ethereum/shanghai/vm/gas.v | 170 + .../shanghai/vm/instructions/__init__.ast | 1804 ++++++++ .../shanghai/vm/instructions/__init__.v | 15 + .../shanghai/vm/instructions/arithmetic.ast | 1289 ++++++ .../shanghai/vm/instructions/arithmetic.v | 387 ++ .../shanghai/vm/instructions/bitwise.ast | 751 +++ .../shanghai/vm/instructions/bitwise.v | 245 + .../shanghai/vm/instructions/block.ast | 495 ++ coq/ethereum/shanghai/vm/instructions/block.v | 249 + .../shanghai/vm/instructions/comparison.ast | 514 +++ .../shanghai/vm/instructions/comparison.v | 206 + .../shanghai/vm/instructions/control_flow.ast | 371 ++ .../shanghai/vm/instructions/control_flow.v | 156 + .../shanghai/vm/instructions/environment.ast | 1828 ++++++++ .../shanghai/vm/instructions/environment.v | 568 +++ .../shanghai/vm/instructions/keccak.ast | 205 + .../shanghai/vm/instructions/keccak.v | 67 + coq/ethereum/shanghai/vm/instructions/log.ast | 323 ++ coq/ethereum/shanghai/vm/instructions/log.v | 61 + .../shanghai/vm/instructions/memory.ast | 463 ++ .../shanghai/vm/instructions/memory.v | 158 + .../shanghai/vm/instructions/stack.ast | 1110 +++++ coq/ethereum/shanghai/vm/instructions/stack.v | 130 + .../shanghai/vm/instructions/storage.ast | 551 +++ .../shanghai/vm/instructions/storage.v | 97 + .../shanghai/vm/instructions/system.ast | 2953 ++++++++++++ .../shanghai/vm/instructions/system.v | 598 +++ coq/ethereum/shanghai/vm/interpreter.ast | 1188 +++++ coq/ethereum/shanghai/vm/interpreter.v | 159 + coq/ethereum/shanghai/vm/memory.ast | 148 + coq/ethereum/shanghai/vm/memory.v | 75 + .../vm/precompiled_contracts/__init__.ast | 97 + .../vm/precompiled_contracts/__init__.v | 16 + .../vm/precompiled_contracts/alt_bn128.ast | 913 ++++ .../vm/precompiled_contracts/alt_bn128.v | 187 + .../vm/precompiled_contracts/blake2f.ast | 137 + .../vm/precompiled_contracts/blake2f.v | 41 + .../vm/precompiled_contracts/ecrecover.ast | 306 ++ .../vm/precompiled_contracts/ecrecover.v | 93 + .../vm/precompiled_contracts/identity.ast | 96 + .../vm/precompiled_contracts/identity.v | 36 + .../vm/precompiled_contracts/mapping.ast | 97 + .../vm/precompiled_contracts/mapping.v | 23 + .../vm/precompiled_contracts/modexp.ast | 638 +++ .../vm/precompiled_contracts/modexp.v | 203 + .../vm/precompiled_contracts/ripemd160.ast | 131 + .../vm/precompiled_contracts/ripemd160.v | 42 + .../vm/precompiled_contracts/sha256.ast | 112 + .../vm/precompiled_contracts/sha256.v | 32 + coq/ethereum/shanghai/vm/runtime.ast | 180 + coq/ethereum/shanghai/vm/runtime.v | 49 + coq/ethereum/shanghai/vm/stack.ast | 109 + coq/ethereum/shanghai/vm/stack.v | 53 + coq/ethereum/spurious_dragon/__init__.ast | 18 + coq/ethereum/spurious_dragon/__init__.v | 9 + coq/ethereum/spurious_dragon/blocks.ast | 218 + coq/ethereum/spurious_dragon/blocks.v | 19 + coq/ethereum/spurious_dragon/bloom.ast | 208 + coq/ethereum/spurious_dragon/bloom.v | 66 + coq/ethereum/spurious_dragon/fork.ast | 3133 +++++++++++++ coq/ethereum/spurious_dragon/fork.v | 756 ++++ coq/ethereum/spurious_dragon/fork_types.ast | 146 + coq/ethereum/spurious_dragon/fork_types.v | 29 + coq/ethereum/spurious_dragon/state.ast | 1500 ++++++ coq/ethereum/spurious_dragon/state.v | 543 +++ coq/ethereum/spurious_dragon/transactions.ast | 106 + coq/ethereum/spurious_dragon/transactions.v | 12 + coq/ethereum/spurious_dragon/trie.ast | 1618 +++++++ coq/ethereum/spurious_dragon/trie.v | 274 ++ .../spurious_dragon/utils/__init__.ast | 5 + coq/ethereum/spurious_dragon/utils/__init__.v | 4 + .../spurious_dragon/utils/address.ast | 139 + coq/ethereum/spurious_dragon/utils/address.v | 67 + .../spurious_dragon/utils/hexadecimal.ast | 124 + .../spurious_dragon/utils/hexadecimal.v | 68 + .../spurious_dragon/utils/message.ast | 234 + coq/ethereum/spurious_dragon/utils/message.v | 56 + coq/ethereum/spurious_dragon/vm/__init__.ast | 501 ++ coq/ethereum/spurious_dragon/vm/__init__.v | 63 + .../spurious_dragon/vm/exceptions.ast | 125 + coq/ethereum/spurious_dragon/vm/exceptions.v | 15 + coq/ethereum/spurious_dragon/vm/gas.ast | 801 ++++ coq/ethereum/spurious_dragon/vm/gas.v | 151 + .../vm/instructions/__init__.ast | 1648 +++++++ .../vm/instructions/__init__.v | 15 + .../vm/instructions/arithmetic.ast | 1289 ++++++ .../vm/instructions/arithmetic.v | 387 ++ .../vm/instructions/bitwise.ast | 418 ++ .../spurious_dragon/vm/instructions/bitwise.v | 156 + .../spurious_dragon/vm/instructions/block.ast | 437 ++ .../spurious_dragon/vm/instructions/block.v | 183 + .../vm/instructions/comparison.ast | 514 +++ .../vm/instructions/comparison.v | 206 + .../vm/instructions/control_flow.ast | 371 ++ .../vm/instructions/control_flow.v | 156 + .../vm/instructions/environment.ast | 1199 +++++ .../vm/instructions/environment.v | 434 ++ .../vm/instructions/keccak.ast | 205 + .../spurious_dragon/vm/instructions/keccak.v | 67 + .../spurious_dragon/vm/instructions/log.ast | 306 ++ .../spurious_dragon/vm/instructions/log.v | 59 + .../vm/instructions/memory.ast | 463 ++ .../spurious_dragon/vm/instructions/memory.v | 158 + .../spurious_dragon/vm/instructions/stack.ast | 1083 +++++ .../spurious_dragon/vm/instructions/stack.v | 133 + .../vm/instructions/storage.ast | 278 ++ .../spurious_dragon/vm/instructions/storage.v | 88 + .../vm/instructions/system.ast | 2058 +++++++++ .../spurious_dragon/vm/instructions/system.v | 383 ++ .../spurious_dragon/vm/interpreter.ast | 1083 +++++ coq/ethereum/spurious_dragon/vm/interpreter.v | 155 + coq/ethereum/spurious_dragon/vm/memory.ast | 148 + coq/ethereum/spurious_dragon/vm/memory.v | 75 + .../vm/precompiled_contracts/__init__.ast | 52 + .../vm/precompiled_contracts/__init__.v | 16 + .../vm/precompiled_contracts/ecrecover.ast | 306 ++ .../vm/precompiled_contracts/ecrecover.v | 93 + .../vm/precompiled_contracts/identity.ast | 96 + .../vm/precompiled_contracts/identity.v | 36 + .../vm/precompiled_contracts/mapping.ast | 65 + .../vm/precompiled_contracts/mapping.v | 20 + .../vm/precompiled_contracts/ripemd160.ast | 131 + .../vm/precompiled_contracts/ripemd160.v | 42 + .../vm/precompiled_contracts/sha256.ast | 112 + .../vm/precompiled_contracts/sha256.v | 32 + coq/ethereum/spurious_dragon/vm/runtime.ast | 180 + coq/ethereum/spurious_dragon/vm/runtime.v | 49 + coq/ethereum/spurious_dragon/vm/stack.ast | 109 + coq/ethereum/spurious_dragon/vm/stack.v | 53 + coq/ethereum/tangerine_whistle/__init__.ast | 18 + coq/ethereum/tangerine_whistle/__init__.v | 8 + coq/ethereum/tangerine_whistle/blocks.ast | 218 + coq/ethereum/tangerine_whistle/blocks.v | 19 + coq/ethereum/tangerine_whistle/bloom.ast | 208 + coq/ethereum/tangerine_whistle/bloom.v | 66 + coq/ethereum/tangerine_whistle/fork.ast | 2908 ++++++++++++ coq/ethereum/tangerine_whistle/fork.v | 744 +++ coq/ethereum/tangerine_whistle/fork_types.ast | 146 + coq/ethereum/tangerine_whistle/fork_types.v | 29 + coq/ethereum/tangerine_whistle/state.ast | 1292 ++++++ coq/ethereum/tangerine_whistle/state.v | 471 ++ .../tangerine_whistle/transactions.ast | 106 + coq/ethereum/tangerine_whistle/transactions.v | 12 + coq/ethereum/tangerine_whistle/trie.ast | 1618 +++++++ coq/ethereum/tangerine_whistle/trie.v | 274 ++ .../tangerine_whistle/utils/__init__.ast | 5 + .../tangerine_whistle/utils/__init__.v | 4 + .../tangerine_whistle/utils/address.ast | 139 + .../tangerine_whistle/utils/address.v | 67 + .../tangerine_whistle/utils/hexadecimal.ast | 124 + .../tangerine_whistle/utils/hexadecimal.v | 68 + .../tangerine_whistle/utils/message.ast | 234 + .../tangerine_whistle/utils/message.v | 56 + .../tangerine_whistle/vm/__init__.ast | 362 ++ coq/ethereum/tangerine_whistle/vm/__init__.v | 56 + .../tangerine_whistle/vm/exceptions.ast | 125 + .../tangerine_whistle/vm/exceptions.v | 15 + coq/ethereum/tangerine_whistle/vm/gas.ast | 801 ++++ coq/ethereum/tangerine_whistle/vm/gas.v | 151 + .../vm/instructions/__init__.ast | 1648 +++++++ .../vm/instructions/__init__.v | 15 + .../vm/instructions/arithmetic.ast | 1289 ++++++ .../vm/instructions/arithmetic.v | 387 ++ .../vm/instructions/bitwise.ast | 418 ++ .../vm/instructions/bitwise.v | 156 + .../vm/instructions/block.ast | 437 ++ .../tangerine_whistle/vm/instructions/block.v | 183 + .../vm/instructions/comparison.ast | 514 +++ .../vm/instructions/comparison.v | 206 + .../vm/instructions/control_flow.ast | 371 ++ .../vm/instructions/control_flow.v | 156 + .../vm/instructions/environment.ast | 1199 +++++ .../vm/instructions/environment.v | 434 ++ .../vm/instructions/keccak.ast | 205 + .../vm/instructions/keccak.v | 67 + .../tangerine_whistle/vm/instructions/log.ast | 306 ++ .../tangerine_whistle/vm/instructions/log.v | 59 + .../vm/instructions/memory.ast | 463 ++ .../vm/instructions/memory.v | 158 + .../vm/instructions/stack.ast | 1083 +++++ .../tangerine_whistle/vm/instructions/stack.v | 133 + .../vm/instructions/storage.ast | 278 ++ .../vm/instructions/storage.v | 88 + .../vm/instructions/system.ast | 1996 ++++++++ .../vm/instructions/system.v | 386 ++ .../tangerine_whistle/vm/interpreter.ast | 975 ++++ .../tangerine_whistle/vm/interpreter.v | 151 + coq/ethereum/tangerine_whistle/vm/memory.ast | 148 + coq/ethereum/tangerine_whistle/vm/memory.v | 75 + .../vm/precompiled_contracts/__init__.ast | 52 + .../vm/precompiled_contracts/__init__.v | 16 + .../vm/precompiled_contracts/ecrecover.ast | 306 ++ .../vm/precompiled_contracts/ecrecover.v | 93 + .../vm/precompiled_contracts/identity.ast | 96 + .../vm/precompiled_contracts/identity.v | 36 + .../vm/precompiled_contracts/mapping.ast | 65 + .../vm/precompiled_contracts/mapping.v | 20 + .../vm/precompiled_contracts/ripemd160.ast | 131 + .../vm/precompiled_contracts/ripemd160.v | 42 + .../vm/precompiled_contracts/sha256.ast | 112 + .../vm/precompiled_contracts/sha256.v | 32 + coq/ethereum/tangerine_whistle/vm/runtime.ast | 180 + coq/ethereum/tangerine_whistle/vm/runtime.v | 49 + coq/ethereum/tangerine_whistle/vm/stack.ast | 109 + coq/ethereum/tangerine_whistle/vm/stack.v | 53 + coq/ethereum/trace.ast | 257 ++ coq/ethereum/trace.v | 26 + coq/ethereum/utils/__init__.ast | 73 + coq/ethereum/utils/__init__.v | 14 + coq/ethereum/utils/byte.ast | 103 + coq/ethereum/utils/byte.v | 55 + coq/ethereum/utils/hexadecimal.ast | 406 ++ coq/ethereum/utils/hexadecimal.v | 206 + coq/ethereum/utils/numeric.ast | 421 ++ coq/ethereum/utils/numeric.v | 186 + coq/ethereum/utils/safe_arithmetic.ast | 175 + coq/ethereum/utils/safe_arithmetic.v | 77 + coq/translate.py | 118 +- coq/translation/bloom.v | 23 - coq/translation/fork.v | 32 - coq/translation/state.v | 27 - coq/translation/trie.v | 26 - coq/translation/utils/address.v | 21 - coq/translation/utils/hexadecimal.v | 17 - coq/translation/utils/message.v | 23 - coq/translation/vm/__init__.v | 24 - coq/translation/vm/gas.v | 22 - coq/translation/vm/instructions/arithmetic.v | 18 - coq/translation/vm/instructions/bitwise.v | 17 - coq/translation/vm/instructions/block.v | 17 - coq/translation/vm/instructions/comparison.v | 17 - .../vm/instructions/control_flow.v | 18 - coq/translation/vm/instructions/environment.v | 25 - coq/translation/vm/instructions/keccak.v | 20 - coq/translation/vm/instructions/log.v | 21 - coq/translation/vm/instructions/memory.v | 20 - coq/translation/vm/instructions/stack.v | 19 - coq/translation/vm/instructions/storage.v | 19 - coq/translation/vm/instructions/system.v | 24 - coq/translation/vm/interpreter.v | 28 - coq/translation/vm/memory.v | 17 - .../vm/precompiled_contracts/alt_bn128.v | 20 - .../vm/precompiled_contracts/blake2f.v | 18 - .../vm/precompiled_contracts/ecrecover.v | 21 - .../vm/precompiled_contracts/identity.v | 18 - .../vm/precompiled_contracts/mapping.v | 24 - .../vm/precompiled_contracts/modexp.v | 19 - .../precompiled_contracts/point_evaluation.v | 20 - .../vm/precompiled_contracts/ripemd160.v | 19 - .../vm/precompiled_contracts/sha256.v | 18 - coq/translation/vm/runtime.v | 17 - coq/translation/vm/stack.v | 17 - 1369 files changed, 474316 insertions(+), 733 deletions(-) create mode 100644 coq/ethereum/__init__.ast create mode 100644 coq/ethereum/__init__.v create mode 100644 coq/ethereum/arrow_glacier/__init__.ast create mode 100644 coq/ethereum/arrow_glacier/__init__.v create mode 100644 coq/ethereum/arrow_glacier/blocks.ast create mode 100644 coq/ethereum/arrow_glacier/blocks.v rename coq/{translation => ethereum/arrow_glacier}/bloom.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/bloom.v rename coq/{translation => ethereum/arrow_glacier}/exceptions.ast (100%) rename coq/{translation => ethereum/arrow_glacier}/exceptions.v (100%) create mode 100644 coq/ethereum/arrow_glacier/fork.ast create mode 100644 coq/ethereum/arrow_glacier/fork.v create mode 100644 coq/ethereum/arrow_glacier/fork_types.ast rename coq/{translation => ethereum/arrow_glacier}/fork_types.v (54%) create mode 100644 coq/ethereum/arrow_glacier/state.ast create mode 100644 coq/ethereum/arrow_glacier/state.v create mode 100644 coq/ethereum/arrow_glacier/transactions.ast create mode 100644 coq/ethereum/arrow_glacier/transactions.v create mode 100644 coq/ethereum/arrow_glacier/trie.ast create mode 100644 coq/ethereum/arrow_glacier/trie.v rename coq/{translation => ethereum/arrow_glacier}/utils/__init__.ast (100%) rename coq/{translation => ethereum/arrow_glacier}/utils/__init__.v (100%) create mode 100644 coq/ethereum/arrow_glacier/utils/address.ast create mode 100644 coq/ethereum/arrow_glacier/utils/address.v create mode 100644 coq/ethereum/arrow_glacier/utils/hexadecimal.ast create mode 100644 coq/ethereum/arrow_glacier/utils/hexadecimal.v create mode 100644 coq/ethereum/arrow_glacier/utils/message.ast create mode 100644 coq/ethereum/arrow_glacier/utils/message.v create mode 100644 coq/ethereum/arrow_glacier/vm/__init__.ast create mode 100644 coq/ethereum/arrow_glacier/vm/__init__.v create mode 100644 coq/ethereum/arrow_glacier/vm/exceptions.ast rename coq/{translation => ethereum/arrow_glacier}/vm/exceptions.v (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/gas.ast create mode 100644 coq/ethereum/arrow_glacier/vm/gas.v create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/__init__.ast rename coq/{translation => ethereum/arrow_glacier}/vm/instructions/__init__.v (94%) rename coq/{translation => ethereum/arrow_glacier}/vm/instructions/arithmetic.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/arithmetic.v rename coq/{translation => ethereum/arrow_glacier}/vm/instructions/bitwise.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/bitwise.v create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/block.ast create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/block.v rename coq/{translation => ethereum/arrow_glacier}/vm/instructions/comparison.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/comparison.v rename coq/{translation => ethereum/arrow_glacier}/vm/instructions/control_flow.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/control_flow.v create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/environment.ast create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/environment.v rename coq/{translation => ethereum/arrow_glacier}/vm/instructions/keccak.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/keccak.v rename coq/{translation => ethereum/arrow_glacier}/vm/instructions/log.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/log.v create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/memory.ast create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/memory.v create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/stack.ast create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/stack.v create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/storage.ast create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/storage.v create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/system.ast create mode 100644 coq/ethereum/arrow_glacier/vm/instructions/system.v create mode 100644 coq/ethereum/arrow_glacier/vm/interpreter.ast create mode 100644 coq/ethereum/arrow_glacier/vm/interpreter.v rename coq/{translation => ethereum/arrow_glacier}/vm/memory.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/memory.v create mode 100644 coq/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.ast create mode 100644 coq/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.v rename coq/{translation => ethereum/arrow_glacier}/vm/precompiled_contracts/alt_bn128.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.v rename coq/{translation => ethereum/arrow_glacier}/vm/precompiled_contracts/blake2f.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.v rename coq/{translation => ethereum/arrow_glacier}/vm/precompiled_contracts/ecrecover.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.v rename coq/{translation => ethereum/arrow_glacier}/vm/precompiled_contracts/identity.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/precompiled_contracts/identity.v create mode 100644 coq/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.ast create mode 100644 coq/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.v rename coq/{translation => ethereum/arrow_glacier}/vm/precompiled_contracts/modexp.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.v rename coq/{translation => ethereum/arrow_glacier}/vm/precompiled_contracts/ripemd160.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.v rename coq/{translation => ethereum/arrow_glacier}/vm/precompiled_contracts/sha256.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.v rename coq/{translation => ethereum/arrow_glacier}/vm/runtime.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/runtime.v rename coq/{translation => ethereum/arrow_glacier}/vm/stack.ast (100%) create mode 100644 coq/ethereum/arrow_glacier/vm/stack.v create mode 100644 coq/ethereum/berlin/__init__.ast create mode 100644 coq/ethereum/berlin/__init__.v create mode 100644 coq/ethereum/berlin/blocks.ast create mode 100644 coq/ethereum/berlin/blocks.v create mode 100644 coq/ethereum/berlin/bloom.ast create mode 100644 coq/ethereum/berlin/bloom.v create mode 100644 coq/ethereum/berlin/exceptions.ast create mode 100644 coq/ethereum/berlin/exceptions.v create mode 100644 coq/ethereum/berlin/fork.ast create mode 100644 coq/ethereum/berlin/fork.v create mode 100644 coq/ethereum/berlin/fork_types.ast create mode 100644 coq/ethereum/berlin/fork_types.v create mode 100644 coq/ethereum/berlin/state.ast create mode 100644 coq/ethereum/berlin/state.v create mode 100644 coq/ethereum/berlin/transactions.ast create mode 100644 coq/ethereum/berlin/transactions.v create mode 100644 coq/ethereum/berlin/trie.ast create mode 100644 coq/ethereum/berlin/trie.v create mode 100644 coq/ethereum/berlin/utils/__init__.ast create mode 100644 coq/ethereum/berlin/utils/__init__.v create mode 100644 coq/ethereum/berlin/utils/address.ast create mode 100644 coq/ethereum/berlin/utils/address.v create mode 100644 coq/ethereum/berlin/utils/hexadecimal.ast create mode 100644 coq/ethereum/berlin/utils/hexadecimal.v create mode 100644 coq/ethereum/berlin/utils/message.ast create mode 100644 coq/ethereum/berlin/utils/message.v create mode 100644 coq/ethereum/berlin/vm/__init__.ast create mode 100644 coq/ethereum/berlin/vm/__init__.v create mode 100644 coq/ethereum/berlin/vm/exceptions.ast create mode 100644 coq/ethereum/berlin/vm/exceptions.v create mode 100644 coq/ethereum/berlin/vm/gas.ast create mode 100644 coq/ethereum/berlin/vm/gas.v create mode 100644 coq/ethereum/berlin/vm/instructions/__init__.ast create mode 100644 coq/ethereum/berlin/vm/instructions/__init__.v create mode 100644 coq/ethereum/berlin/vm/instructions/arithmetic.ast create mode 100644 coq/ethereum/berlin/vm/instructions/arithmetic.v create mode 100644 coq/ethereum/berlin/vm/instructions/bitwise.ast create mode 100644 coq/ethereum/berlin/vm/instructions/bitwise.v create mode 100644 coq/ethereum/berlin/vm/instructions/block.ast create mode 100644 coq/ethereum/berlin/vm/instructions/block.v create mode 100644 coq/ethereum/berlin/vm/instructions/comparison.ast create mode 100644 coq/ethereum/berlin/vm/instructions/comparison.v create mode 100644 coq/ethereum/berlin/vm/instructions/control_flow.ast create mode 100644 coq/ethereum/berlin/vm/instructions/control_flow.v create mode 100644 coq/ethereum/berlin/vm/instructions/environment.ast create mode 100644 coq/ethereum/berlin/vm/instructions/environment.v create mode 100644 coq/ethereum/berlin/vm/instructions/keccak.ast create mode 100644 coq/ethereum/berlin/vm/instructions/keccak.v create mode 100644 coq/ethereum/berlin/vm/instructions/log.ast create mode 100644 coq/ethereum/berlin/vm/instructions/log.v create mode 100644 coq/ethereum/berlin/vm/instructions/memory.ast create mode 100644 coq/ethereum/berlin/vm/instructions/memory.v create mode 100644 coq/ethereum/berlin/vm/instructions/stack.ast create mode 100644 coq/ethereum/berlin/vm/instructions/stack.v create mode 100644 coq/ethereum/berlin/vm/instructions/storage.ast create mode 100644 coq/ethereum/berlin/vm/instructions/storage.v create mode 100644 coq/ethereum/berlin/vm/instructions/system.ast create mode 100644 coq/ethereum/berlin/vm/instructions/system.v create mode 100644 coq/ethereum/berlin/vm/interpreter.ast create mode 100644 coq/ethereum/berlin/vm/interpreter.v create mode 100644 coq/ethereum/berlin/vm/memory.ast create mode 100644 coq/ethereum/berlin/vm/memory.v create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/__init__.ast create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/__init__.v create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/alt_bn128.ast create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/alt_bn128.v create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/blake2f.ast create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/blake2f.v create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/ecrecover.ast create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/ecrecover.v create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/identity.ast create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/identity.v create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/mapping.ast create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/mapping.v create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/modexp.ast create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/modexp.v create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/ripemd160.ast create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/ripemd160.v create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/sha256.ast create mode 100644 coq/ethereum/berlin/vm/precompiled_contracts/sha256.v create mode 100644 coq/ethereum/berlin/vm/runtime.ast create mode 100644 coq/ethereum/berlin/vm/runtime.v create mode 100644 coq/ethereum/berlin/vm/stack.ast create mode 100644 coq/ethereum/berlin/vm/stack.v create mode 100644 coq/ethereum/byzantium/__init__.ast create mode 100644 coq/ethereum/byzantium/__init__.v create mode 100644 coq/ethereum/byzantium/blocks.ast create mode 100644 coq/ethereum/byzantium/blocks.v create mode 100644 coq/ethereum/byzantium/bloom.ast create mode 100644 coq/ethereum/byzantium/bloom.v create mode 100644 coq/ethereum/byzantium/fork.ast create mode 100644 coq/ethereum/byzantium/fork.v create mode 100644 coq/ethereum/byzantium/fork_types.ast create mode 100644 coq/ethereum/byzantium/fork_types.v create mode 100644 coq/ethereum/byzantium/state.ast create mode 100644 coq/ethereum/byzantium/state.v create mode 100644 coq/ethereum/byzantium/transactions.ast rename coq/{translation => ethereum/byzantium}/transactions.v (89%) create mode 100644 coq/ethereum/byzantium/trie.ast create mode 100644 coq/ethereum/byzantium/trie.v create mode 100644 coq/ethereum/byzantium/utils/__init__.ast create mode 100644 coq/ethereum/byzantium/utils/__init__.v create mode 100644 coq/ethereum/byzantium/utils/address.ast create mode 100644 coq/ethereum/byzantium/utils/address.v create mode 100644 coq/ethereum/byzantium/utils/hexadecimal.ast create mode 100644 coq/ethereum/byzantium/utils/hexadecimal.v create mode 100644 coq/ethereum/byzantium/utils/message.ast create mode 100644 coq/ethereum/byzantium/utils/message.v create mode 100644 coq/ethereum/byzantium/vm/__init__.ast create mode 100644 coq/ethereum/byzantium/vm/__init__.v create mode 100644 coq/ethereum/byzantium/vm/exceptions.ast create mode 100644 coq/ethereum/byzantium/vm/exceptions.v create mode 100644 coq/ethereum/byzantium/vm/gas.ast create mode 100644 coq/ethereum/byzantium/vm/gas.v create mode 100644 coq/ethereum/byzantium/vm/instructions/__init__.ast create mode 100644 coq/ethereum/byzantium/vm/instructions/__init__.v create mode 100644 coq/ethereum/byzantium/vm/instructions/arithmetic.ast create mode 100644 coq/ethereum/byzantium/vm/instructions/arithmetic.v create mode 100644 coq/ethereum/byzantium/vm/instructions/bitwise.ast create mode 100644 coq/ethereum/byzantium/vm/instructions/bitwise.v create mode 100644 coq/ethereum/byzantium/vm/instructions/block.ast create mode 100644 coq/ethereum/byzantium/vm/instructions/block.v create mode 100644 coq/ethereum/byzantium/vm/instructions/comparison.ast create mode 100644 coq/ethereum/byzantium/vm/instructions/comparison.v create mode 100644 coq/ethereum/byzantium/vm/instructions/control_flow.ast create mode 100644 coq/ethereum/byzantium/vm/instructions/control_flow.v create mode 100644 coq/ethereum/byzantium/vm/instructions/environment.ast create mode 100644 coq/ethereum/byzantium/vm/instructions/environment.v create mode 100644 coq/ethereum/byzantium/vm/instructions/keccak.ast create mode 100644 coq/ethereum/byzantium/vm/instructions/keccak.v create mode 100644 coq/ethereum/byzantium/vm/instructions/log.ast create mode 100644 coq/ethereum/byzantium/vm/instructions/log.v create mode 100644 coq/ethereum/byzantium/vm/instructions/memory.ast create mode 100644 coq/ethereum/byzantium/vm/instructions/memory.v create mode 100644 coq/ethereum/byzantium/vm/instructions/stack.ast create mode 100644 coq/ethereum/byzantium/vm/instructions/stack.v create mode 100644 coq/ethereum/byzantium/vm/instructions/storage.ast create mode 100644 coq/ethereum/byzantium/vm/instructions/storage.v create mode 100644 coq/ethereum/byzantium/vm/instructions/system.ast create mode 100644 coq/ethereum/byzantium/vm/instructions/system.v create mode 100644 coq/ethereum/byzantium/vm/interpreter.ast create mode 100644 coq/ethereum/byzantium/vm/interpreter.v create mode 100644 coq/ethereum/byzantium/vm/memory.ast create mode 100644 coq/ethereum/byzantium/vm/memory.v create mode 100644 coq/ethereum/byzantium/vm/precompiled_contracts/__init__.ast create mode 100644 coq/ethereum/byzantium/vm/precompiled_contracts/__init__.v create mode 100644 coq/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.ast create mode 100644 coq/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.v create mode 100644 coq/ethereum/byzantium/vm/precompiled_contracts/ecrecover.ast create mode 100644 coq/ethereum/byzantium/vm/precompiled_contracts/ecrecover.v create mode 100644 coq/ethereum/byzantium/vm/precompiled_contracts/identity.ast create mode 100644 coq/ethereum/byzantium/vm/precompiled_contracts/identity.v create mode 100644 coq/ethereum/byzantium/vm/precompiled_contracts/mapping.ast create mode 100644 coq/ethereum/byzantium/vm/precompiled_contracts/mapping.v create mode 100644 coq/ethereum/byzantium/vm/precompiled_contracts/modexp.ast create mode 100644 coq/ethereum/byzantium/vm/precompiled_contracts/modexp.v create mode 100644 coq/ethereum/byzantium/vm/precompiled_contracts/ripemd160.ast create mode 100644 coq/ethereum/byzantium/vm/precompiled_contracts/ripemd160.v create mode 100644 coq/ethereum/byzantium/vm/precompiled_contracts/sha256.ast create mode 100644 coq/ethereum/byzantium/vm/precompiled_contracts/sha256.v create mode 100644 coq/ethereum/byzantium/vm/runtime.ast create mode 100644 coq/ethereum/byzantium/vm/runtime.v create mode 100644 coq/ethereum/byzantium/vm/stack.ast create mode 100644 coq/ethereum/byzantium/vm/stack.v rename coq/{translation => ethereum/cancun}/__init__.ast (100%) rename coq/{translation => ethereum/cancun}/__init__.v (100%) rename coq/{translation => ethereum/cancun}/blocks.ast (100%) create mode 100644 coq/ethereum/cancun/blocks.v create mode 100644 coq/ethereum/cancun/bloom.ast create mode 100644 coq/ethereum/cancun/bloom.v create mode 100644 coq/ethereum/cancun/exceptions.ast create mode 100644 coq/ethereum/cancun/exceptions.v rename coq/{translation => ethereum/cancun}/fork.ast (100%) create mode 100644 coq/ethereum/cancun/fork.v rename coq/{translation => ethereum/cancun}/fork_types.ast (100%) create mode 100644 coq/ethereum/cancun/fork_types.v rename coq/{translation => ethereum/cancun}/state.ast (100%) create mode 100644 coq/ethereum/cancun/state.v rename coq/{translation => ethereum/cancun}/transactions.ast (100%) create mode 100644 coq/ethereum/cancun/transactions.v rename coq/{translation => ethereum/cancun}/trie.ast (100%) create mode 100644 coq/ethereum/cancun/trie.v create mode 100644 coq/ethereum/cancun/utils/__init__.ast create mode 100644 coq/ethereum/cancun/utils/__init__.v rename coq/{translation => ethereum/cancun}/utils/address.ast (100%) create mode 100644 coq/ethereum/cancun/utils/address.v rename coq/{translation => ethereum/cancun}/utils/hexadecimal.ast (100%) create mode 100644 coq/ethereum/cancun/utils/hexadecimal.v rename coq/{translation => ethereum/cancun}/utils/message.ast (100%) create mode 100644 coq/ethereum/cancun/utils/message.v rename coq/{translation => ethereum/cancun}/vm/__init__.ast (100%) create mode 100644 coq/ethereum/cancun/vm/__init__.v rename coq/{translation => ethereum/cancun}/vm/exceptions.ast (100%) create mode 100644 coq/ethereum/cancun/vm/exceptions.v rename coq/{translation => ethereum/cancun}/vm/gas.ast (100%) create mode 100644 coq/ethereum/cancun/vm/gas.v rename coq/{translation => ethereum/cancun}/vm/instructions/__init__.ast (100%) create mode 100644 coq/ethereum/cancun/vm/instructions/__init__.v create mode 100644 coq/ethereum/cancun/vm/instructions/arithmetic.ast create mode 100644 coq/ethereum/cancun/vm/instructions/arithmetic.v create mode 100644 coq/ethereum/cancun/vm/instructions/bitwise.ast create mode 100644 coq/ethereum/cancun/vm/instructions/bitwise.v rename coq/{translation => ethereum/cancun}/vm/instructions/block.ast (100%) create mode 100644 coq/ethereum/cancun/vm/instructions/block.v create mode 100644 coq/ethereum/cancun/vm/instructions/comparison.ast create mode 100644 coq/ethereum/cancun/vm/instructions/comparison.v create mode 100644 coq/ethereum/cancun/vm/instructions/control_flow.ast create mode 100644 coq/ethereum/cancun/vm/instructions/control_flow.v rename coq/{translation => ethereum/cancun}/vm/instructions/environment.ast (100%) create mode 100644 coq/ethereum/cancun/vm/instructions/environment.v create mode 100644 coq/ethereum/cancun/vm/instructions/keccak.ast create mode 100644 coq/ethereum/cancun/vm/instructions/keccak.v create mode 100644 coq/ethereum/cancun/vm/instructions/log.ast create mode 100644 coq/ethereum/cancun/vm/instructions/log.v rename coq/{translation => ethereum/cancun}/vm/instructions/memory.ast (100%) create mode 100644 coq/ethereum/cancun/vm/instructions/memory.v rename coq/{translation => ethereum/cancun}/vm/instructions/stack.ast (100%) create mode 100644 coq/ethereum/cancun/vm/instructions/stack.v rename coq/{translation => ethereum/cancun}/vm/instructions/storage.ast (100%) create mode 100644 coq/ethereum/cancun/vm/instructions/storage.v rename coq/{translation => ethereum/cancun}/vm/instructions/system.ast (100%) create mode 100644 coq/ethereum/cancun/vm/instructions/system.v rename coq/{translation => ethereum/cancun}/vm/interpreter.ast (100%) create mode 100644 coq/ethereum/cancun/vm/interpreter.v create mode 100644 coq/ethereum/cancun/vm/memory.ast create mode 100644 coq/ethereum/cancun/vm/memory.v rename coq/{translation => ethereum/cancun}/vm/precompiled_contracts/__init__.ast (100%) create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/__init__.v create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/alt_bn128.ast create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/alt_bn128.v create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/blake2f.ast create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/blake2f.v create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/ecrecover.ast create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/ecrecover.v create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/identity.ast create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/identity.v rename coq/{translation => ethereum/cancun}/vm/precompiled_contracts/mapping.ast (100%) create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/mapping.v create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/modexp.ast create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/modexp.v rename coq/{translation => ethereum/cancun}/vm/precompiled_contracts/point_evaluation.ast (100%) create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/point_evaluation.v create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/ripemd160.ast create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/ripemd160.v create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/sha256.ast create mode 100644 coq/ethereum/cancun/vm/precompiled_contracts/sha256.v create mode 100644 coq/ethereum/cancun/vm/runtime.ast create mode 100644 coq/ethereum/cancun/vm/runtime.v create mode 100644 coq/ethereum/cancun/vm/stack.ast create mode 100644 coq/ethereum/cancun/vm/stack.v create mode 100644 coq/ethereum/constantinople/__init__.ast create mode 100644 coq/ethereum/constantinople/__init__.v create mode 100644 coq/ethereum/constantinople/blocks.ast create mode 100644 coq/ethereum/constantinople/blocks.v create mode 100644 coq/ethereum/constantinople/bloom.ast create mode 100644 coq/ethereum/constantinople/bloom.v create mode 100644 coq/ethereum/constantinople/fork.ast create mode 100644 coq/ethereum/constantinople/fork.v create mode 100644 coq/ethereum/constantinople/fork_types.ast create mode 100644 coq/ethereum/constantinople/fork_types.v create mode 100644 coq/ethereum/constantinople/state.ast create mode 100644 coq/ethereum/constantinople/state.v create mode 100644 coq/ethereum/constantinople/transactions.ast create mode 100644 coq/ethereum/constantinople/transactions.v create mode 100644 coq/ethereum/constantinople/trie.ast create mode 100644 coq/ethereum/constantinople/trie.v create mode 100644 coq/ethereum/constantinople/utils/__init__.ast create mode 100644 coq/ethereum/constantinople/utils/__init__.v create mode 100644 coq/ethereum/constantinople/utils/address.ast create mode 100644 coq/ethereum/constantinople/utils/address.v create mode 100644 coq/ethereum/constantinople/utils/hexadecimal.ast create mode 100644 coq/ethereum/constantinople/utils/hexadecimal.v create mode 100644 coq/ethereum/constantinople/utils/message.ast create mode 100644 coq/ethereum/constantinople/utils/message.v create mode 100644 coq/ethereum/constantinople/vm/__init__.ast create mode 100644 coq/ethereum/constantinople/vm/__init__.v create mode 100644 coq/ethereum/constantinople/vm/exceptions.ast create mode 100644 coq/ethereum/constantinople/vm/exceptions.v create mode 100644 coq/ethereum/constantinople/vm/gas.ast create mode 100644 coq/ethereum/constantinople/vm/gas.v create mode 100644 coq/ethereum/constantinople/vm/instructions/__init__.ast create mode 100644 coq/ethereum/constantinople/vm/instructions/__init__.v create mode 100644 coq/ethereum/constantinople/vm/instructions/arithmetic.ast create mode 100644 coq/ethereum/constantinople/vm/instructions/arithmetic.v create mode 100644 coq/ethereum/constantinople/vm/instructions/bitwise.ast create mode 100644 coq/ethereum/constantinople/vm/instructions/bitwise.v create mode 100644 coq/ethereum/constantinople/vm/instructions/block.ast create mode 100644 coq/ethereum/constantinople/vm/instructions/block.v create mode 100644 coq/ethereum/constantinople/vm/instructions/comparison.ast create mode 100644 coq/ethereum/constantinople/vm/instructions/comparison.v create mode 100644 coq/ethereum/constantinople/vm/instructions/control_flow.ast create mode 100644 coq/ethereum/constantinople/vm/instructions/control_flow.v create mode 100644 coq/ethereum/constantinople/vm/instructions/environment.ast create mode 100644 coq/ethereum/constantinople/vm/instructions/environment.v create mode 100644 coq/ethereum/constantinople/vm/instructions/keccak.ast create mode 100644 coq/ethereum/constantinople/vm/instructions/keccak.v create mode 100644 coq/ethereum/constantinople/vm/instructions/log.ast create mode 100644 coq/ethereum/constantinople/vm/instructions/log.v create mode 100644 coq/ethereum/constantinople/vm/instructions/memory.ast create mode 100644 coq/ethereum/constantinople/vm/instructions/memory.v create mode 100644 coq/ethereum/constantinople/vm/instructions/stack.ast create mode 100644 coq/ethereum/constantinople/vm/instructions/stack.v create mode 100644 coq/ethereum/constantinople/vm/instructions/storage.ast create mode 100644 coq/ethereum/constantinople/vm/instructions/storage.v create mode 100644 coq/ethereum/constantinople/vm/instructions/system.ast create mode 100644 coq/ethereum/constantinople/vm/instructions/system.v create mode 100644 coq/ethereum/constantinople/vm/interpreter.ast create mode 100644 coq/ethereum/constantinople/vm/interpreter.v create mode 100644 coq/ethereum/constantinople/vm/memory.ast create mode 100644 coq/ethereum/constantinople/vm/memory.v create mode 100644 coq/ethereum/constantinople/vm/precompiled_contracts/__init__.ast create mode 100644 coq/ethereum/constantinople/vm/precompiled_contracts/__init__.v create mode 100644 coq/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.ast create mode 100644 coq/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.v create mode 100644 coq/ethereum/constantinople/vm/precompiled_contracts/ecrecover.ast create mode 100644 coq/ethereum/constantinople/vm/precompiled_contracts/ecrecover.v create mode 100644 coq/ethereum/constantinople/vm/precompiled_contracts/identity.ast create mode 100644 coq/ethereum/constantinople/vm/precompiled_contracts/identity.v create mode 100644 coq/ethereum/constantinople/vm/precompiled_contracts/mapping.ast create mode 100644 coq/ethereum/constantinople/vm/precompiled_contracts/mapping.v create mode 100644 coq/ethereum/constantinople/vm/precompiled_contracts/modexp.ast create mode 100644 coq/ethereum/constantinople/vm/precompiled_contracts/modexp.v create mode 100644 coq/ethereum/constantinople/vm/precompiled_contracts/ripemd160.ast create mode 100644 coq/ethereum/constantinople/vm/precompiled_contracts/ripemd160.v create mode 100644 coq/ethereum/constantinople/vm/precompiled_contracts/sha256.ast create mode 100644 coq/ethereum/constantinople/vm/precompiled_contracts/sha256.v create mode 100644 coq/ethereum/constantinople/vm/runtime.ast create mode 100644 coq/ethereum/constantinople/vm/runtime.v create mode 100644 coq/ethereum/constantinople/vm/stack.ast create mode 100644 coq/ethereum/constantinople/vm/stack.v create mode 100644 coq/ethereum/crypto/__init__.ast create mode 100644 coq/ethereum/crypto/__init__.v create mode 100644 coq/ethereum/crypto/alt_bn128.ast create mode 100644 coq/ethereum/crypto/alt_bn128.v create mode 100644 coq/ethereum/crypto/blake2.ast create mode 100644 coq/ethereum/crypto/blake2.v create mode 100644 coq/ethereum/crypto/elliptic_curve.ast create mode 100644 coq/ethereum/crypto/elliptic_curve.v create mode 100644 coq/ethereum/crypto/finite_field.ast create mode 100644 coq/ethereum/crypto/finite_field.v create mode 100644 coq/ethereum/crypto/hash.ast create mode 100644 coq/ethereum/crypto/hash.v create mode 100644 coq/ethereum/crypto/kzg.ast create mode 100644 coq/ethereum/crypto/kzg.v create mode 100644 coq/ethereum/dao_fork/__init__.ast create mode 100644 coq/ethereum/dao_fork/__init__.v create mode 100644 coq/ethereum/dao_fork/blocks.ast create mode 100644 coq/ethereum/dao_fork/blocks.v create mode 100644 coq/ethereum/dao_fork/bloom.ast create mode 100644 coq/ethereum/dao_fork/bloom.v create mode 100644 coq/ethereum/dao_fork/dao.ast create mode 100644 coq/ethereum/dao_fork/dao.v create mode 100644 coq/ethereum/dao_fork/fork.ast create mode 100644 coq/ethereum/dao_fork/fork.v create mode 100644 coq/ethereum/dao_fork/fork_types.ast create mode 100644 coq/ethereum/dao_fork/fork_types.v create mode 100644 coq/ethereum/dao_fork/state.ast create mode 100644 coq/ethereum/dao_fork/state.v create mode 100644 coq/ethereum/dao_fork/transactions.ast create mode 100644 coq/ethereum/dao_fork/transactions.v create mode 100644 coq/ethereum/dao_fork/trie.ast create mode 100644 coq/ethereum/dao_fork/trie.v create mode 100644 coq/ethereum/dao_fork/utils/__init__.ast create mode 100644 coq/ethereum/dao_fork/utils/__init__.v create mode 100644 coq/ethereum/dao_fork/utils/address.ast create mode 100644 coq/ethereum/dao_fork/utils/address.v create mode 100644 coq/ethereum/dao_fork/utils/hexadecimal.ast create mode 100644 coq/ethereum/dao_fork/utils/hexadecimal.v create mode 100644 coq/ethereum/dao_fork/utils/message.ast create mode 100644 coq/ethereum/dao_fork/utils/message.v create mode 100644 coq/ethereum/dao_fork/vm/__init__.ast create mode 100644 coq/ethereum/dao_fork/vm/__init__.v create mode 100644 coq/ethereum/dao_fork/vm/exceptions.ast create mode 100644 coq/ethereum/dao_fork/vm/exceptions.v create mode 100644 coq/ethereum/dao_fork/vm/gas.ast create mode 100644 coq/ethereum/dao_fork/vm/gas.v create mode 100644 coq/ethereum/dao_fork/vm/instructions/__init__.ast create mode 100644 coq/ethereum/dao_fork/vm/instructions/__init__.v create mode 100644 coq/ethereum/dao_fork/vm/instructions/arithmetic.ast create mode 100644 coq/ethereum/dao_fork/vm/instructions/arithmetic.v create mode 100644 coq/ethereum/dao_fork/vm/instructions/bitwise.ast create mode 100644 coq/ethereum/dao_fork/vm/instructions/bitwise.v create mode 100644 coq/ethereum/dao_fork/vm/instructions/block.ast create mode 100644 coq/ethereum/dao_fork/vm/instructions/block.v create mode 100644 coq/ethereum/dao_fork/vm/instructions/comparison.ast create mode 100644 coq/ethereum/dao_fork/vm/instructions/comparison.v create mode 100644 coq/ethereum/dao_fork/vm/instructions/control_flow.ast create mode 100644 coq/ethereum/dao_fork/vm/instructions/control_flow.v create mode 100644 coq/ethereum/dao_fork/vm/instructions/environment.ast create mode 100644 coq/ethereum/dao_fork/vm/instructions/environment.v create mode 100644 coq/ethereum/dao_fork/vm/instructions/keccak.ast create mode 100644 coq/ethereum/dao_fork/vm/instructions/keccak.v create mode 100644 coq/ethereum/dao_fork/vm/instructions/log.ast create mode 100644 coq/ethereum/dao_fork/vm/instructions/log.v create mode 100644 coq/ethereum/dao_fork/vm/instructions/memory.ast create mode 100644 coq/ethereum/dao_fork/vm/instructions/memory.v create mode 100644 coq/ethereum/dao_fork/vm/instructions/stack.ast create mode 100644 coq/ethereum/dao_fork/vm/instructions/stack.v create mode 100644 coq/ethereum/dao_fork/vm/instructions/storage.ast create mode 100644 coq/ethereum/dao_fork/vm/instructions/storage.v create mode 100644 coq/ethereum/dao_fork/vm/instructions/system.ast create mode 100644 coq/ethereum/dao_fork/vm/instructions/system.v create mode 100644 coq/ethereum/dao_fork/vm/interpreter.ast create mode 100644 coq/ethereum/dao_fork/vm/interpreter.v create mode 100644 coq/ethereum/dao_fork/vm/memory.ast create mode 100644 coq/ethereum/dao_fork/vm/memory.v create mode 100644 coq/ethereum/dao_fork/vm/precompiled_contracts/__init__.ast create mode 100644 coq/ethereum/dao_fork/vm/precompiled_contracts/__init__.v create mode 100644 coq/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.ast create mode 100644 coq/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.v create mode 100644 coq/ethereum/dao_fork/vm/precompiled_contracts/identity.ast create mode 100644 coq/ethereum/dao_fork/vm/precompiled_contracts/identity.v create mode 100644 coq/ethereum/dao_fork/vm/precompiled_contracts/mapping.ast create mode 100644 coq/ethereum/dao_fork/vm/precompiled_contracts/mapping.v create mode 100644 coq/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.ast create mode 100644 coq/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.v create mode 100644 coq/ethereum/dao_fork/vm/precompiled_contracts/sha256.ast create mode 100644 coq/ethereum/dao_fork/vm/precompiled_contracts/sha256.v create mode 100644 coq/ethereum/dao_fork/vm/runtime.ast create mode 100644 coq/ethereum/dao_fork/vm/runtime.v create mode 100644 coq/ethereum/dao_fork/vm/stack.ast create mode 100644 coq/ethereum/dao_fork/vm/stack.v create mode 100644 coq/ethereum/ethash.ast create mode 100644 coq/ethereum/ethash.v create mode 100644 coq/ethereum/exceptions.ast create mode 100644 coq/ethereum/exceptions.v create mode 100644 coq/ethereum/fork_criteria.ast create mode 100644 coq/ethereum/fork_criteria.v create mode 100644 coq/ethereum/frontier/__init__.ast create mode 100644 coq/ethereum/frontier/__init__.v create mode 100644 coq/ethereum/frontier/blocks.ast create mode 100644 coq/ethereum/frontier/blocks.v create mode 100644 coq/ethereum/frontier/bloom.ast create mode 100644 coq/ethereum/frontier/bloom.v create mode 100644 coq/ethereum/frontier/fork.ast create mode 100644 coq/ethereum/frontier/fork.v create mode 100644 coq/ethereum/frontier/fork_types.ast create mode 100644 coq/ethereum/frontier/fork_types.v create mode 100644 coq/ethereum/frontier/state.ast create mode 100644 coq/ethereum/frontier/state.v create mode 100644 coq/ethereum/frontier/transactions.ast create mode 100644 coq/ethereum/frontier/transactions.v create mode 100644 coq/ethereum/frontier/trie.ast create mode 100644 coq/ethereum/frontier/trie.v create mode 100644 coq/ethereum/frontier/utils/__init__.ast create mode 100644 coq/ethereum/frontier/utils/__init__.v create mode 100644 coq/ethereum/frontier/utils/address.ast create mode 100644 coq/ethereum/frontier/utils/address.v create mode 100644 coq/ethereum/frontier/utils/hexadecimal.ast create mode 100644 coq/ethereum/frontier/utils/hexadecimal.v create mode 100644 coq/ethereum/frontier/utils/message.ast create mode 100644 coq/ethereum/frontier/utils/message.v create mode 100644 coq/ethereum/frontier/vm/__init__.ast create mode 100644 coq/ethereum/frontier/vm/__init__.v create mode 100644 coq/ethereum/frontier/vm/exceptions.ast create mode 100644 coq/ethereum/frontier/vm/exceptions.v create mode 100644 coq/ethereum/frontier/vm/gas.ast create mode 100644 coq/ethereum/frontier/vm/gas.v create mode 100644 coq/ethereum/frontier/vm/instructions/__init__.ast create mode 100644 coq/ethereum/frontier/vm/instructions/__init__.v create mode 100644 coq/ethereum/frontier/vm/instructions/arithmetic.ast create mode 100644 coq/ethereum/frontier/vm/instructions/arithmetic.v create mode 100644 coq/ethereum/frontier/vm/instructions/bitwise.ast create mode 100644 coq/ethereum/frontier/vm/instructions/bitwise.v create mode 100644 coq/ethereum/frontier/vm/instructions/block.ast create mode 100644 coq/ethereum/frontier/vm/instructions/block.v create mode 100644 coq/ethereum/frontier/vm/instructions/comparison.ast create mode 100644 coq/ethereum/frontier/vm/instructions/comparison.v create mode 100644 coq/ethereum/frontier/vm/instructions/control_flow.ast create mode 100644 coq/ethereum/frontier/vm/instructions/control_flow.v create mode 100644 coq/ethereum/frontier/vm/instructions/environment.ast create mode 100644 coq/ethereum/frontier/vm/instructions/environment.v create mode 100644 coq/ethereum/frontier/vm/instructions/keccak.ast create mode 100644 coq/ethereum/frontier/vm/instructions/keccak.v create mode 100644 coq/ethereum/frontier/vm/instructions/log.ast create mode 100644 coq/ethereum/frontier/vm/instructions/log.v create mode 100644 coq/ethereum/frontier/vm/instructions/memory.ast create mode 100644 coq/ethereum/frontier/vm/instructions/memory.v create mode 100644 coq/ethereum/frontier/vm/instructions/stack.ast create mode 100644 coq/ethereum/frontier/vm/instructions/stack.v create mode 100644 coq/ethereum/frontier/vm/instructions/storage.ast create mode 100644 coq/ethereum/frontier/vm/instructions/storage.v create mode 100644 coq/ethereum/frontier/vm/instructions/system.ast create mode 100644 coq/ethereum/frontier/vm/instructions/system.v create mode 100644 coq/ethereum/frontier/vm/interpreter.ast create mode 100644 coq/ethereum/frontier/vm/interpreter.v create mode 100644 coq/ethereum/frontier/vm/memory.ast create mode 100644 coq/ethereum/frontier/vm/memory.v create mode 100644 coq/ethereum/frontier/vm/precompiled_contracts/__init__.ast create mode 100644 coq/ethereum/frontier/vm/precompiled_contracts/__init__.v create mode 100644 coq/ethereum/frontier/vm/precompiled_contracts/ecrecover.ast create mode 100644 coq/ethereum/frontier/vm/precompiled_contracts/ecrecover.v create mode 100644 coq/ethereum/frontier/vm/precompiled_contracts/identity.ast create mode 100644 coq/ethereum/frontier/vm/precompiled_contracts/identity.v create mode 100644 coq/ethereum/frontier/vm/precompiled_contracts/mapping.ast create mode 100644 coq/ethereum/frontier/vm/precompiled_contracts/mapping.v create mode 100644 coq/ethereum/frontier/vm/precompiled_contracts/ripemd160.ast create mode 100644 coq/ethereum/frontier/vm/precompiled_contracts/ripemd160.v create mode 100644 coq/ethereum/frontier/vm/precompiled_contracts/sha256.ast create mode 100644 coq/ethereum/frontier/vm/precompiled_contracts/sha256.v create mode 100644 coq/ethereum/frontier/vm/runtime.ast create mode 100644 coq/ethereum/frontier/vm/runtime.v create mode 100644 coq/ethereum/frontier/vm/stack.ast create mode 100644 coq/ethereum/frontier/vm/stack.v create mode 100644 coq/ethereum/genesis.ast create mode 100644 coq/ethereum/genesis.v create mode 100644 coq/ethereum/gray_glacier/__init__.ast create mode 100644 coq/ethereum/gray_glacier/__init__.v create mode 100644 coq/ethereum/gray_glacier/blocks.ast create mode 100644 coq/ethereum/gray_glacier/blocks.v create mode 100644 coq/ethereum/gray_glacier/bloom.ast create mode 100644 coq/ethereum/gray_glacier/bloom.v create mode 100644 coq/ethereum/gray_glacier/exceptions.ast create mode 100644 coq/ethereum/gray_glacier/exceptions.v create mode 100644 coq/ethereum/gray_glacier/fork.ast create mode 100644 coq/ethereum/gray_glacier/fork.v create mode 100644 coq/ethereum/gray_glacier/fork_types.ast create mode 100644 coq/ethereum/gray_glacier/fork_types.v create mode 100644 coq/ethereum/gray_glacier/state.ast create mode 100644 coq/ethereum/gray_glacier/state.v create mode 100644 coq/ethereum/gray_glacier/transactions.ast create mode 100644 coq/ethereum/gray_glacier/transactions.v create mode 100644 coq/ethereum/gray_glacier/trie.ast create mode 100644 coq/ethereum/gray_glacier/trie.v create mode 100644 coq/ethereum/gray_glacier/utils/__init__.ast create mode 100644 coq/ethereum/gray_glacier/utils/__init__.v create mode 100644 coq/ethereum/gray_glacier/utils/address.ast create mode 100644 coq/ethereum/gray_glacier/utils/address.v create mode 100644 coq/ethereum/gray_glacier/utils/hexadecimal.ast create mode 100644 coq/ethereum/gray_glacier/utils/hexadecimal.v create mode 100644 coq/ethereum/gray_glacier/utils/message.ast create mode 100644 coq/ethereum/gray_glacier/utils/message.v create mode 100644 coq/ethereum/gray_glacier/vm/__init__.ast create mode 100644 coq/ethereum/gray_glacier/vm/__init__.v create mode 100644 coq/ethereum/gray_glacier/vm/exceptions.ast create mode 100644 coq/ethereum/gray_glacier/vm/exceptions.v create mode 100644 coq/ethereum/gray_glacier/vm/gas.ast create mode 100644 coq/ethereum/gray_glacier/vm/gas.v create mode 100644 coq/ethereum/gray_glacier/vm/instructions/__init__.ast create mode 100644 coq/ethereum/gray_glacier/vm/instructions/__init__.v create mode 100644 coq/ethereum/gray_glacier/vm/instructions/arithmetic.ast create mode 100644 coq/ethereum/gray_glacier/vm/instructions/arithmetic.v create mode 100644 coq/ethereum/gray_glacier/vm/instructions/bitwise.ast create mode 100644 coq/ethereum/gray_glacier/vm/instructions/bitwise.v create mode 100644 coq/ethereum/gray_glacier/vm/instructions/block.ast create mode 100644 coq/ethereum/gray_glacier/vm/instructions/block.v create mode 100644 coq/ethereum/gray_glacier/vm/instructions/comparison.ast create mode 100644 coq/ethereum/gray_glacier/vm/instructions/comparison.v create mode 100644 coq/ethereum/gray_glacier/vm/instructions/control_flow.ast create mode 100644 coq/ethereum/gray_glacier/vm/instructions/control_flow.v create mode 100644 coq/ethereum/gray_glacier/vm/instructions/environment.ast create mode 100644 coq/ethereum/gray_glacier/vm/instructions/environment.v create mode 100644 coq/ethereum/gray_glacier/vm/instructions/keccak.ast create mode 100644 coq/ethereum/gray_glacier/vm/instructions/keccak.v create mode 100644 coq/ethereum/gray_glacier/vm/instructions/log.ast create mode 100644 coq/ethereum/gray_glacier/vm/instructions/log.v create mode 100644 coq/ethereum/gray_glacier/vm/instructions/memory.ast create mode 100644 coq/ethereum/gray_glacier/vm/instructions/memory.v create mode 100644 coq/ethereum/gray_glacier/vm/instructions/stack.ast create mode 100644 coq/ethereum/gray_glacier/vm/instructions/stack.v create mode 100644 coq/ethereum/gray_glacier/vm/instructions/storage.ast create mode 100644 coq/ethereum/gray_glacier/vm/instructions/storage.v create mode 100644 coq/ethereum/gray_glacier/vm/instructions/system.ast create mode 100644 coq/ethereum/gray_glacier/vm/instructions/system.v create mode 100644 coq/ethereum/gray_glacier/vm/interpreter.ast create mode 100644 coq/ethereum/gray_glacier/vm/interpreter.v create mode 100644 coq/ethereum/gray_glacier/vm/memory.ast create mode 100644 coq/ethereum/gray_glacier/vm/memory.v create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/__init__.ast create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/__init__.v create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.ast create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.v create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.ast create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.v create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.ast create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.v create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/identity.ast create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/identity.v create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/mapping.ast create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/mapping.v create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/modexp.ast create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/modexp.v create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.ast create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.v create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/sha256.ast create mode 100644 coq/ethereum/gray_glacier/vm/precompiled_contracts/sha256.v create mode 100644 coq/ethereum/gray_glacier/vm/runtime.ast create mode 100644 coq/ethereum/gray_glacier/vm/runtime.v create mode 100644 coq/ethereum/gray_glacier/vm/stack.ast create mode 100644 coq/ethereum/gray_glacier/vm/stack.v create mode 100644 coq/ethereum/homestead/__init__.ast create mode 100644 coq/ethereum/homestead/__init__.v create mode 100644 coq/ethereum/homestead/blocks.ast create mode 100644 coq/ethereum/homestead/blocks.v create mode 100644 coq/ethereum/homestead/bloom.ast create mode 100644 coq/ethereum/homestead/bloom.v create mode 100644 coq/ethereum/homestead/fork.ast create mode 100644 coq/ethereum/homestead/fork.v create mode 100644 coq/ethereum/homestead/fork_types.ast create mode 100644 coq/ethereum/homestead/fork_types.v create mode 100644 coq/ethereum/homestead/state.ast create mode 100644 coq/ethereum/homestead/state.v create mode 100644 coq/ethereum/homestead/transactions.ast create mode 100644 coq/ethereum/homestead/transactions.v create mode 100644 coq/ethereum/homestead/trie.ast create mode 100644 coq/ethereum/homestead/trie.v create mode 100644 coq/ethereum/homestead/utils/__init__.ast create mode 100644 coq/ethereum/homestead/utils/__init__.v create mode 100644 coq/ethereum/homestead/utils/address.ast create mode 100644 coq/ethereum/homestead/utils/address.v create mode 100644 coq/ethereum/homestead/utils/hexadecimal.ast create mode 100644 coq/ethereum/homestead/utils/hexadecimal.v create mode 100644 coq/ethereum/homestead/utils/message.ast create mode 100644 coq/ethereum/homestead/utils/message.v create mode 100644 coq/ethereum/homestead/vm/__init__.ast create mode 100644 coq/ethereum/homestead/vm/__init__.v create mode 100644 coq/ethereum/homestead/vm/exceptions.ast create mode 100644 coq/ethereum/homestead/vm/exceptions.v create mode 100644 coq/ethereum/homestead/vm/gas.ast create mode 100644 coq/ethereum/homestead/vm/gas.v create mode 100644 coq/ethereum/homestead/vm/instructions/__init__.ast create mode 100644 coq/ethereum/homestead/vm/instructions/__init__.v create mode 100644 coq/ethereum/homestead/vm/instructions/arithmetic.ast create mode 100644 coq/ethereum/homestead/vm/instructions/arithmetic.v create mode 100644 coq/ethereum/homestead/vm/instructions/bitwise.ast create mode 100644 coq/ethereum/homestead/vm/instructions/bitwise.v create mode 100644 coq/ethereum/homestead/vm/instructions/block.ast create mode 100644 coq/ethereum/homestead/vm/instructions/block.v create mode 100644 coq/ethereum/homestead/vm/instructions/comparison.ast create mode 100644 coq/ethereum/homestead/vm/instructions/comparison.v create mode 100644 coq/ethereum/homestead/vm/instructions/control_flow.ast create mode 100644 coq/ethereum/homestead/vm/instructions/control_flow.v create mode 100644 coq/ethereum/homestead/vm/instructions/environment.ast create mode 100644 coq/ethereum/homestead/vm/instructions/environment.v create mode 100644 coq/ethereum/homestead/vm/instructions/keccak.ast create mode 100644 coq/ethereum/homestead/vm/instructions/keccak.v create mode 100644 coq/ethereum/homestead/vm/instructions/log.ast create mode 100644 coq/ethereum/homestead/vm/instructions/log.v create mode 100644 coq/ethereum/homestead/vm/instructions/memory.ast create mode 100644 coq/ethereum/homestead/vm/instructions/memory.v create mode 100644 coq/ethereum/homestead/vm/instructions/stack.ast create mode 100644 coq/ethereum/homestead/vm/instructions/stack.v create mode 100644 coq/ethereum/homestead/vm/instructions/storage.ast create mode 100644 coq/ethereum/homestead/vm/instructions/storage.v create mode 100644 coq/ethereum/homestead/vm/instructions/system.ast create mode 100644 coq/ethereum/homestead/vm/instructions/system.v create mode 100644 coq/ethereum/homestead/vm/interpreter.ast create mode 100644 coq/ethereum/homestead/vm/interpreter.v create mode 100644 coq/ethereum/homestead/vm/memory.ast create mode 100644 coq/ethereum/homestead/vm/memory.v create mode 100644 coq/ethereum/homestead/vm/precompiled_contracts/__init__.ast create mode 100644 coq/ethereum/homestead/vm/precompiled_contracts/__init__.v create mode 100644 coq/ethereum/homestead/vm/precompiled_contracts/ecrecover.ast create mode 100644 coq/ethereum/homestead/vm/precompiled_contracts/ecrecover.v create mode 100644 coq/ethereum/homestead/vm/precompiled_contracts/identity.ast create mode 100644 coq/ethereum/homestead/vm/precompiled_contracts/identity.v create mode 100644 coq/ethereum/homestead/vm/precompiled_contracts/mapping.ast create mode 100644 coq/ethereum/homestead/vm/precompiled_contracts/mapping.v create mode 100644 coq/ethereum/homestead/vm/precompiled_contracts/ripemd160.ast create mode 100644 coq/ethereum/homestead/vm/precompiled_contracts/ripemd160.v create mode 100644 coq/ethereum/homestead/vm/precompiled_contracts/sha256.ast create mode 100644 coq/ethereum/homestead/vm/precompiled_contracts/sha256.v create mode 100644 coq/ethereum/homestead/vm/runtime.ast create mode 100644 coq/ethereum/homestead/vm/runtime.v create mode 100644 coq/ethereum/homestead/vm/stack.ast create mode 100644 coq/ethereum/homestead/vm/stack.v create mode 100644 coq/ethereum/istanbul/__init__.ast create mode 100644 coq/ethereum/istanbul/__init__.v create mode 100644 coq/ethereum/istanbul/blocks.ast create mode 100644 coq/ethereum/istanbul/blocks.v create mode 100644 coq/ethereum/istanbul/bloom.ast create mode 100644 coq/ethereum/istanbul/bloom.v create mode 100644 coq/ethereum/istanbul/fork.ast create mode 100644 coq/ethereum/istanbul/fork.v create mode 100644 coq/ethereum/istanbul/fork_types.ast create mode 100644 coq/ethereum/istanbul/fork_types.v create mode 100644 coq/ethereum/istanbul/state.ast create mode 100644 coq/ethereum/istanbul/state.v create mode 100644 coq/ethereum/istanbul/transactions.ast create mode 100644 coq/ethereum/istanbul/transactions.v create mode 100644 coq/ethereum/istanbul/trie.ast create mode 100644 coq/ethereum/istanbul/trie.v create mode 100644 coq/ethereum/istanbul/utils/__init__.ast create mode 100644 coq/ethereum/istanbul/utils/__init__.v create mode 100644 coq/ethereum/istanbul/utils/address.ast create mode 100644 coq/ethereum/istanbul/utils/address.v create mode 100644 coq/ethereum/istanbul/utils/hexadecimal.ast create mode 100644 coq/ethereum/istanbul/utils/hexadecimal.v create mode 100644 coq/ethereum/istanbul/utils/message.ast create mode 100644 coq/ethereum/istanbul/utils/message.v create mode 100644 coq/ethereum/istanbul/vm/__init__.ast create mode 100644 coq/ethereum/istanbul/vm/__init__.v create mode 100644 coq/ethereum/istanbul/vm/exceptions.ast create mode 100644 coq/ethereum/istanbul/vm/exceptions.v create mode 100644 coq/ethereum/istanbul/vm/gas.ast create mode 100644 coq/ethereum/istanbul/vm/gas.v create mode 100644 coq/ethereum/istanbul/vm/instructions/__init__.ast create mode 100644 coq/ethereum/istanbul/vm/instructions/__init__.v create mode 100644 coq/ethereum/istanbul/vm/instructions/arithmetic.ast create mode 100644 coq/ethereum/istanbul/vm/instructions/arithmetic.v create mode 100644 coq/ethereum/istanbul/vm/instructions/bitwise.ast create mode 100644 coq/ethereum/istanbul/vm/instructions/bitwise.v create mode 100644 coq/ethereum/istanbul/vm/instructions/block.ast create mode 100644 coq/ethereum/istanbul/vm/instructions/block.v create mode 100644 coq/ethereum/istanbul/vm/instructions/comparison.ast create mode 100644 coq/ethereum/istanbul/vm/instructions/comparison.v create mode 100644 coq/ethereum/istanbul/vm/instructions/control_flow.ast create mode 100644 coq/ethereum/istanbul/vm/instructions/control_flow.v create mode 100644 coq/ethereum/istanbul/vm/instructions/environment.ast create mode 100644 coq/ethereum/istanbul/vm/instructions/environment.v create mode 100644 coq/ethereum/istanbul/vm/instructions/keccak.ast create mode 100644 coq/ethereum/istanbul/vm/instructions/keccak.v create mode 100644 coq/ethereum/istanbul/vm/instructions/log.ast create mode 100644 coq/ethereum/istanbul/vm/instructions/log.v create mode 100644 coq/ethereum/istanbul/vm/instructions/memory.ast create mode 100644 coq/ethereum/istanbul/vm/instructions/memory.v create mode 100644 coq/ethereum/istanbul/vm/instructions/stack.ast create mode 100644 coq/ethereum/istanbul/vm/instructions/stack.v create mode 100644 coq/ethereum/istanbul/vm/instructions/storage.ast create mode 100644 coq/ethereum/istanbul/vm/instructions/storage.v create mode 100644 coq/ethereum/istanbul/vm/instructions/system.ast create mode 100644 coq/ethereum/istanbul/vm/instructions/system.v create mode 100644 coq/ethereum/istanbul/vm/interpreter.ast create mode 100644 coq/ethereum/istanbul/vm/interpreter.v create mode 100644 coq/ethereum/istanbul/vm/memory.ast create mode 100644 coq/ethereum/istanbul/vm/memory.v create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/__init__.ast create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/__init__.v create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.ast create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.v create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/blake2f.ast create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/blake2f.v create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/ecrecover.ast create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/ecrecover.v create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/identity.ast create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/identity.v create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/mapping.ast create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/mapping.v create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/modexp.ast create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/modexp.v create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/ripemd160.ast create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/ripemd160.v create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/sha256.ast create mode 100644 coq/ethereum/istanbul/vm/precompiled_contracts/sha256.v create mode 100644 coq/ethereum/istanbul/vm/runtime.ast create mode 100644 coq/ethereum/istanbul/vm/runtime.v create mode 100644 coq/ethereum/istanbul/vm/stack.ast create mode 100644 coq/ethereum/istanbul/vm/stack.v create mode 100644 coq/ethereum/london/__init__.ast create mode 100644 coq/ethereum/london/__init__.v create mode 100644 coq/ethereum/london/blocks.ast create mode 100644 coq/ethereum/london/blocks.v create mode 100644 coq/ethereum/london/bloom.ast create mode 100644 coq/ethereum/london/bloom.v create mode 100644 coq/ethereum/london/exceptions.ast create mode 100644 coq/ethereum/london/exceptions.v create mode 100644 coq/ethereum/london/fork.ast create mode 100644 coq/ethereum/london/fork.v create mode 100644 coq/ethereum/london/fork_types.ast create mode 100644 coq/ethereum/london/fork_types.v create mode 100644 coq/ethereum/london/state.ast create mode 100644 coq/ethereum/london/state.v create mode 100644 coq/ethereum/london/transactions.ast create mode 100644 coq/ethereum/london/transactions.v create mode 100644 coq/ethereum/london/trie.ast create mode 100644 coq/ethereum/london/trie.v create mode 100644 coq/ethereum/london/utils/__init__.ast create mode 100644 coq/ethereum/london/utils/__init__.v create mode 100644 coq/ethereum/london/utils/address.ast create mode 100644 coq/ethereum/london/utils/address.v create mode 100644 coq/ethereum/london/utils/hexadecimal.ast create mode 100644 coq/ethereum/london/utils/hexadecimal.v create mode 100644 coq/ethereum/london/utils/message.ast create mode 100644 coq/ethereum/london/utils/message.v create mode 100644 coq/ethereum/london/vm/__init__.ast create mode 100644 coq/ethereum/london/vm/__init__.v create mode 100644 coq/ethereum/london/vm/exceptions.ast create mode 100644 coq/ethereum/london/vm/exceptions.v create mode 100644 coq/ethereum/london/vm/gas.ast create mode 100644 coq/ethereum/london/vm/gas.v create mode 100644 coq/ethereum/london/vm/instructions/__init__.ast create mode 100644 coq/ethereum/london/vm/instructions/__init__.v create mode 100644 coq/ethereum/london/vm/instructions/arithmetic.ast create mode 100644 coq/ethereum/london/vm/instructions/arithmetic.v create mode 100644 coq/ethereum/london/vm/instructions/bitwise.ast create mode 100644 coq/ethereum/london/vm/instructions/bitwise.v create mode 100644 coq/ethereum/london/vm/instructions/block.ast create mode 100644 coq/ethereum/london/vm/instructions/block.v create mode 100644 coq/ethereum/london/vm/instructions/comparison.ast create mode 100644 coq/ethereum/london/vm/instructions/comparison.v create mode 100644 coq/ethereum/london/vm/instructions/control_flow.ast create mode 100644 coq/ethereum/london/vm/instructions/control_flow.v create mode 100644 coq/ethereum/london/vm/instructions/environment.ast create mode 100644 coq/ethereum/london/vm/instructions/environment.v create mode 100644 coq/ethereum/london/vm/instructions/keccak.ast create mode 100644 coq/ethereum/london/vm/instructions/keccak.v create mode 100644 coq/ethereum/london/vm/instructions/log.ast create mode 100644 coq/ethereum/london/vm/instructions/log.v create mode 100644 coq/ethereum/london/vm/instructions/memory.ast create mode 100644 coq/ethereum/london/vm/instructions/memory.v create mode 100644 coq/ethereum/london/vm/instructions/stack.ast create mode 100644 coq/ethereum/london/vm/instructions/stack.v create mode 100644 coq/ethereum/london/vm/instructions/storage.ast create mode 100644 coq/ethereum/london/vm/instructions/storage.v create mode 100644 coq/ethereum/london/vm/instructions/system.ast create mode 100644 coq/ethereum/london/vm/instructions/system.v create mode 100644 coq/ethereum/london/vm/interpreter.ast create mode 100644 coq/ethereum/london/vm/interpreter.v create mode 100644 coq/ethereum/london/vm/memory.ast create mode 100644 coq/ethereum/london/vm/memory.v create mode 100644 coq/ethereum/london/vm/precompiled_contracts/__init__.ast create mode 100644 coq/ethereum/london/vm/precompiled_contracts/__init__.v create mode 100644 coq/ethereum/london/vm/precompiled_contracts/alt_bn128.ast create mode 100644 coq/ethereum/london/vm/precompiled_contracts/alt_bn128.v create mode 100644 coq/ethereum/london/vm/precompiled_contracts/blake2f.ast create mode 100644 coq/ethereum/london/vm/precompiled_contracts/blake2f.v create mode 100644 coq/ethereum/london/vm/precompiled_contracts/ecrecover.ast create mode 100644 coq/ethereum/london/vm/precompiled_contracts/ecrecover.v create mode 100644 coq/ethereum/london/vm/precompiled_contracts/identity.ast create mode 100644 coq/ethereum/london/vm/precompiled_contracts/identity.v create mode 100644 coq/ethereum/london/vm/precompiled_contracts/mapping.ast create mode 100644 coq/ethereum/london/vm/precompiled_contracts/mapping.v create mode 100644 coq/ethereum/london/vm/precompiled_contracts/modexp.ast create mode 100644 coq/ethereum/london/vm/precompiled_contracts/modexp.v create mode 100644 coq/ethereum/london/vm/precompiled_contracts/ripemd160.ast create mode 100644 coq/ethereum/london/vm/precompiled_contracts/ripemd160.v create mode 100644 coq/ethereum/london/vm/precompiled_contracts/sha256.ast create mode 100644 coq/ethereum/london/vm/precompiled_contracts/sha256.v create mode 100644 coq/ethereum/london/vm/runtime.ast create mode 100644 coq/ethereum/london/vm/runtime.v create mode 100644 coq/ethereum/london/vm/stack.ast create mode 100644 coq/ethereum/london/vm/stack.v create mode 100644 coq/ethereum/muir_glacier/__init__.ast create mode 100644 coq/ethereum/muir_glacier/__init__.v create mode 100644 coq/ethereum/muir_glacier/blocks.ast create mode 100644 coq/ethereum/muir_glacier/blocks.v create mode 100644 coq/ethereum/muir_glacier/bloom.ast create mode 100644 coq/ethereum/muir_glacier/bloom.v create mode 100644 coq/ethereum/muir_glacier/fork.ast create mode 100644 coq/ethereum/muir_glacier/fork.v create mode 100644 coq/ethereum/muir_glacier/fork_types.ast create mode 100644 coq/ethereum/muir_glacier/fork_types.v create mode 100644 coq/ethereum/muir_glacier/state.ast create mode 100644 coq/ethereum/muir_glacier/state.v create mode 100644 coq/ethereum/muir_glacier/transactions.ast create mode 100644 coq/ethereum/muir_glacier/transactions.v create mode 100644 coq/ethereum/muir_glacier/trie.ast create mode 100644 coq/ethereum/muir_glacier/trie.v create mode 100644 coq/ethereum/muir_glacier/utils/__init__.ast create mode 100644 coq/ethereum/muir_glacier/utils/__init__.v create mode 100644 coq/ethereum/muir_glacier/utils/address.ast create mode 100644 coq/ethereum/muir_glacier/utils/address.v create mode 100644 coq/ethereum/muir_glacier/utils/hexadecimal.ast create mode 100644 coq/ethereum/muir_glacier/utils/hexadecimal.v create mode 100644 coq/ethereum/muir_glacier/utils/message.ast create mode 100644 coq/ethereum/muir_glacier/utils/message.v create mode 100644 coq/ethereum/muir_glacier/vm/__init__.ast create mode 100644 coq/ethereum/muir_glacier/vm/__init__.v create mode 100644 coq/ethereum/muir_glacier/vm/exceptions.ast create mode 100644 coq/ethereum/muir_glacier/vm/exceptions.v create mode 100644 coq/ethereum/muir_glacier/vm/gas.ast create mode 100644 coq/ethereum/muir_glacier/vm/gas.v create mode 100644 coq/ethereum/muir_glacier/vm/instructions/__init__.ast create mode 100644 coq/ethereum/muir_glacier/vm/instructions/__init__.v create mode 100644 coq/ethereum/muir_glacier/vm/instructions/arithmetic.ast create mode 100644 coq/ethereum/muir_glacier/vm/instructions/arithmetic.v create mode 100644 coq/ethereum/muir_glacier/vm/instructions/bitwise.ast create mode 100644 coq/ethereum/muir_glacier/vm/instructions/bitwise.v create mode 100644 coq/ethereum/muir_glacier/vm/instructions/block.ast create mode 100644 coq/ethereum/muir_glacier/vm/instructions/block.v create mode 100644 coq/ethereum/muir_glacier/vm/instructions/comparison.ast create mode 100644 coq/ethereum/muir_glacier/vm/instructions/comparison.v create mode 100644 coq/ethereum/muir_glacier/vm/instructions/control_flow.ast create mode 100644 coq/ethereum/muir_glacier/vm/instructions/control_flow.v create mode 100644 coq/ethereum/muir_glacier/vm/instructions/environment.ast create mode 100644 coq/ethereum/muir_glacier/vm/instructions/environment.v create mode 100644 coq/ethereum/muir_glacier/vm/instructions/keccak.ast create mode 100644 coq/ethereum/muir_glacier/vm/instructions/keccak.v create mode 100644 coq/ethereum/muir_glacier/vm/instructions/log.ast create mode 100644 coq/ethereum/muir_glacier/vm/instructions/log.v create mode 100644 coq/ethereum/muir_glacier/vm/instructions/memory.ast create mode 100644 coq/ethereum/muir_glacier/vm/instructions/memory.v create mode 100644 coq/ethereum/muir_glacier/vm/instructions/stack.ast create mode 100644 coq/ethereum/muir_glacier/vm/instructions/stack.v create mode 100644 coq/ethereum/muir_glacier/vm/instructions/storage.ast create mode 100644 coq/ethereum/muir_glacier/vm/instructions/storage.v create mode 100644 coq/ethereum/muir_glacier/vm/instructions/system.ast create mode 100644 coq/ethereum/muir_glacier/vm/instructions/system.v create mode 100644 coq/ethereum/muir_glacier/vm/interpreter.ast create mode 100644 coq/ethereum/muir_glacier/vm/interpreter.v create mode 100644 coq/ethereum/muir_glacier/vm/memory.ast create mode 100644 coq/ethereum/muir_glacier/vm/memory.v create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/__init__.ast create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/__init__.v create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.ast create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.v create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.ast create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.v create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.ast create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.v create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/identity.ast create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/identity.v create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/mapping.ast create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/mapping.v create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/modexp.ast create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/modexp.v create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.ast create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.v create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/sha256.ast create mode 100644 coq/ethereum/muir_glacier/vm/precompiled_contracts/sha256.v create mode 100644 coq/ethereum/muir_glacier/vm/runtime.ast create mode 100644 coq/ethereum/muir_glacier/vm/runtime.v create mode 100644 coq/ethereum/muir_glacier/vm/stack.ast create mode 100644 coq/ethereum/muir_glacier/vm/stack.v create mode 100644 coq/ethereum/paris/__init__.ast create mode 100644 coq/ethereum/paris/__init__.v create mode 100644 coq/ethereum/paris/blocks.ast rename coq/{translation => ethereum/paris}/blocks.v (87%) create mode 100644 coq/ethereum/paris/bloom.ast create mode 100644 coq/ethereum/paris/bloom.v create mode 100644 coq/ethereum/paris/exceptions.ast create mode 100644 coq/ethereum/paris/exceptions.v create mode 100644 coq/ethereum/paris/fork.ast create mode 100644 coq/ethereum/paris/fork.v create mode 100644 coq/ethereum/paris/fork_types.ast create mode 100644 coq/ethereum/paris/fork_types.v create mode 100644 coq/ethereum/paris/state.ast create mode 100644 coq/ethereum/paris/state.v create mode 100644 coq/ethereum/paris/transactions.ast create mode 100644 coq/ethereum/paris/transactions.v create mode 100644 coq/ethereum/paris/trie.ast create mode 100644 coq/ethereum/paris/trie.v create mode 100644 coq/ethereum/paris/utils/__init__.ast create mode 100644 coq/ethereum/paris/utils/__init__.v create mode 100644 coq/ethereum/paris/utils/address.ast create mode 100644 coq/ethereum/paris/utils/address.v create mode 100644 coq/ethereum/paris/utils/hexadecimal.ast create mode 100644 coq/ethereum/paris/utils/hexadecimal.v create mode 100644 coq/ethereum/paris/utils/message.ast create mode 100644 coq/ethereum/paris/utils/message.v create mode 100644 coq/ethereum/paris/vm/__init__.ast create mode 100644 coq/ethereum/paris/vm/__init__.v create mode 100644 coq/ethereum/paris/vm/exceptions.ast create mode 100644 coq/ethereum/paris/vm/exceptions.v create mode 100644 coq/ethereum/paris/vm/gas.ast create mode 100644 coq/ethereum/paris/vm/gas.v create mode 100644 coq/ethereum/paris/vm/instructions/__init__.ast create mode 100644 coq/ethereum/paris/vm/instructions/__init__.v create mode 100644 coq/ethereum/paris/vm/instructions/arithmetic.ast create mode 100644 coq/ethereum/paris/vm/instructions/arithmetic.v create mode 100644 coq/ethereum/paris/vm/instructions/bitwise.ast create mode 100644 coq/ethereum/paris/vm/instructions/bitwise.v create mode 100644 coq/ethereum/paris/vm/instructions/block.ast create mode 100644 coq/ethereum/paris/vm/instructions/block.v create mode 100644 coq/ethereum/paris/vm/instructions/comparison.ast create mode 100644 coq/ethereum/paris/vm/instructions/comparison.v create mode 100644 coq/ethereum/paris/vm/instructions/control_flow.ast create mode 100644 coq/ethereum/paris/vm/instructions/control_flow.v create mode 100644 coq/ethereum/paris/vm/instructions/environment.ast create mode 100644 coq/ethereum/paris/vm/instructions/environment.v create mode 100644 coq/ethereum/paris/vm/instructions/keccak.ast create mode 100644 coq/ethereum/paris/vm/instructions/keccak.v create mode 100644 coq/ethereum/paris/vm/instructions/log.ast create mode 100644 coq/ethereum/paris/vm/instructions/log.v create mode 100644 coq/ethereum/paris/vm/instructions/memory.ast create mode 100644 coq/ethereum/paris/vm/instructions/memory.v create mode 100644 coq/ethereum/paris/vm/instructions/stack.ast create mode 100644 coq/ethereum/paris/vm/instructions/stack.v create mode 100644 coq/ethereum/paris/vm/instructions/storage.ast create mode 100644 coq/ethereum/paris/vm/instructions/storage.v create mode 100644 coq/ethereum/paris/vm/instructions/system.ast create mode 100644 coq/ethereum/paris/vm/instructions/system.v create mode 100644 coq/ethereum/paris/vm/interpreter.ast create mode 100644 coq/ethereum/paris/vm/interpreter.v create mode 100644 coq/ethereum/paris/vm/memory.ast create mode 100644 coq/ethereum/paris/vm/memory.v create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/__init__.ast rename coq/{translation => ethereum/paris}/vm/precompiled_contracts/__init__.v (87%) create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/alt_bn128.ast create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/alt_bn128.v create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/blake2f.ast create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/blake2f.v create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/ecrecover.ast create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/ecrecover.v create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/identity.ast create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/identity.v create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/mapping.ast create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/mapping.v create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/modexp.ast create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/modexp.v create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/ripemd160.ast create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/ripemd160.v create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/sha256.ast create mode 100644 coq/ethereum/paris/vm/precompiled_contracts/sha256.v create mode 100644 coq/ethereum/paris/vm/runtime.ast create mode 100644 coq/ethereum/paris/vm/runtime.v create mode 100644 coq/ethereum/paris/vm/stack.ast create mode 100644 coq/ethereum/paris/vm/stack.v create mode 100644 coq/ethereum/rlp.ast create mode 100644 coq/ethereum/rlp.v create mode 100644 coq/ethereum/shanghai/__init__.ast create mode 100644 coq/ethereum/shanghai/__init__.v create mode 100644 coq/ethereum/shanghai/blocks.ast create mode 100644 coq/ethereum/shanghai/blocks.v create mode 100644 coq/ethereum/shanghai/bloom.ast create mode 100644 coq/ethereum/shanghai/bloom.v create mode 100644 coq/ethereum/shanghai/exceptions.ast create mode 100644 coq/ethereum/shanghai/exceptions.v create mode 100644 coq/ethereum/shanghai/fork.ast create mode 100644 coq/ethereum/shanghai/fork.v create mode 100644 coq/ethereum/shanghai/fork_types.ast create mode 100644 coq/ethereum/shanghai/fork_types.v create mode 100644 coq/ethereum/shanghai/state.ast create mode 100644 coq/ethereum/shanghai/state.v create mode 100644 coq/ethereum/shanghai/transactions.ast create mode 100644 coq/ethereum/shanghai/transactions.v create mode 100644 coq/ethereum/shanghai/trie.ast create mode 100644 coq/ethereum/shanghai/trie.v create mode 100644 coq/ethereum/shanghai/utils/__init__.ast create mode 100644 coq/ethereum/shanghai/utils/__init__.v create mode 100644 coq/ethereum/shanghai/utils/address.ast create mode 100644 coq/ethereum/shanghai/utils/address.v create mode 100644 coq/ethereum/shanghai/utils/hexadecimal.ast create mode 100644 coq/ethereum/shanghai/utils/hexadecimal.v create mode 100644 coq/ethereum/shanghai/utils/message.ast create mode 100644 coq/ethereum/shanghai/utils/message.v create mode 100644 coq/ethereum/shanghai/vm/__init__.ast create mode 100644 coq/ethereum/shanghai/vm/__init__.v create mode 100644 coq/ethereum/shanghai/vm/exceptions.ast create mode 100644 coq/ethereum/shanghai/vm/exceptions.v create mode 100644 coq/ethereum/shanghai/vm/gas.ast create mode 100644 coq/ethereum/shanghai/vm/gas.v create mode 100644 coq/ethereum/shanghai/vm/instructions/__init__.ast create mode 100644 coq/ethereum/shanghai/vm/instructions/__init__.v create mode 100644 coq/ethereum/shanghai/vm/instructions/arithmetic.ast create mode 100644 coq/ethereum/shanghai/vm/instructions/arithmetic.v create mode 100644 coq/ethereum/shanghai/vm/instructions/bitwise.ast create mode 100644 coq/ethereum/shanghai/vm/instructions/bitwise.v create mode 100644 coq/ethereum/shanghai/vm/instructions/block.ast create mode 100644 coq/ethereum/shanghai/vm/instructions/block.v create mode 100644 coq/ethereum/shanghai/vm/instructions/comparison.ast create mode 100644 coq/ethereum/shanghai/vm/instructions/comparison.v create mode 100644 coq/ethereum/shanghai/vm/instructions/control_flow.ast create mode 100644 coq/ethereum/shanghai/vm/instructions/control_flow.v create mode 100644 coq/ethereum/shanghai/vm/instructions/environment.ast create mode 100644 coq/ethereum/shanghai/vm/instructions/environment.v create mode 100644 coq/ethereum/shanghai/vm/instructions/keccak.ast create mode 100644 coq/ethereum/shanghai/vm/instructions/keccak.v create mode 100644 coq/ethereum/shanghai/vm/instructions/log.ast create mode 100644 coq/ethereum/shanghai/vm/instructions/log.v create mode 100644 coq/ethereum/shanghai/vm/instructions/memory.ast create mode 100644 coq/ethereum/shanghai/vm/instructions/memory.v create mode 100644 coq/ethereum/shanghai/vm/instructions/stack.ast create mode 100644 coq/ethereum/shanghai/vm/instructions/stack.v create mode 100644 coq/ethereum/shanghai/vm/instructions/storage.ast create mode 100644 coq/ethereum/shanghai/vm/instructions/storage.v create mode 100644 coq/ethereum/shanghai/vm/instructions/system.ast create mode 100644 coq/ethereum/shanghai/vm/instructions/system.v create mode 100644 coq/ethereum/shanghai/vm/interpreter.ast create mode 100644 coq/ethereum/shanghai/vm/interpreter.v create mode 100644 coq/ethereum/shanghai/vm/memory.ast create mode 100644 coq/ethereum/shanghai/vm/memory.v create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/__init__.ast create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/__init__.v create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.ast create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.v create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/blake2f.ast create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/blake2f.v create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/ecrecover.ast create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/ecrecover.v create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/identity.ast create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/identity.v create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/mapping.ast create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/mapping.v create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/modexp.ast create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/modexp.v create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/ripemd160.ast create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/ripemd160.v create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/sha256.ast create mode 100644 coq/ethereum/shanghai/vm/precompiled_contracts/sha256.v create mode 100644 coq/ethereum/shanghai/vm/runtime.ast create mode 100644 coq/ethereum/shanghai/vm/runtime.v create mode 100644 coq/ethereum/shanghai/vm/stack.ast create mode 100644 coq/ethereum/shanghai/vm/stack.v create mode 100644 coq/ethereum/spurious_dragon/__init__.ast create mode 100644 coq/ethereum/spurious_dragon/__init__.v create mode 100644 coq/ethereum/spurious_dragon/blocks.ast create mode 100644 coq/ethereum/spurious_dragon/blocks.v create mode 100644 coq/ethereum/spurious_dragon/bloom.ast create mode 100644 coq/ethereum/spurious_dragon/bloom.v create mode 100644 coq/ethereum/spurious_dragon/fork.ast create mode 100644 coq/ethereum/spurious_dragon/fork.v create mode 100644 coq/ethereum/spurious_dragon/fork_types.ast create mode 100644 coq/ethereum/spurious_dragon/fork_types.v create mode 100644 coq/ethereum/spurious_dragon/state.ast create mode 100644 coq/ethereum/spurious_dragon/state.v create mode 100644 coq/ethereum/spurious_dragon/transactions.ast create mode 100644 coq/ethereum/spurious_dragon/transactions.v create mode 100644 coq/ethereum/spurious_dragon/trie.ast create mode 100644 coq/ethereum/spurious_dragon/trie.v create mode 100644 coq/ethereum/spurious_dragon/utils/__init__.ast create mode 100644 coq/ethereum/spurious_dragon/utils/__init__.v create mode 100644 coq/ethereum/spurious_dragon/utils/address.ast create mode 100644 coq/ethereum/spurious_dragon/utils/address.v create mode 100644 coq/ethereum/spurious_dragon/utils/hexadecimal.ast create mode 100644 coq/ethereum/spurious_dragon/utils/hexadecimal.v create mode 100644 coq/ethereum/spurious_dragon/utils/message.ast create mode 100644 coq/ethereum/spurious_dragon/utils/message.v create mode 100644 coq/ethereum/spurious_dragon/vm/__init__.ast create mode 100644 coq/ethereum/spurious_dragon/vm/__init__.v create mode 100644 coq/ethereum/spurious_dragon/vm/exceptions.ast create mode 100644 coq/ethereum/spurious_dragon/vm/exceptions.v create mode 100644 coq/ethereum/spurious_dragon/vm/gas.ast create mode 100644 coq/ethereum/spurious_dragon/vm/gas.v create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/__init__.ast create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/__init__.v create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/arithmetic.ast create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/arithmetic.v create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/bitwise.ast create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/bitwise.v create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/block.ast create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/block.v create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/comparison.ast create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/comparison.v create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/control_flow.ast create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/control_flow.v create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/environment.ast create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/environment.v create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/keccak.ast create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/keccak.v create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/log.ast create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/log.v create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/memory.ast create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/memory.v create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/stack.ast create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/stack.v create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/storage.ast create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/storage.v create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/system.ast create mode 100644 coq/ethereum/spurious_dragon/vm/instructions/system.v create mode 100644 coq/ethereum/spurious_dragon/vm/interpreter.ast create mode 100644 coq/ethereum/spurious_dragon/vm/interpreter.v create mode 100644 coq/ethereum/spurious_dragon/vm/memory.ast create mode 100644 coq/ethereum/spurious_dragon/vm/memory.v create mode 100644 coq/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.ast create mode 100644 coq/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.v create mode 100644 coq/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.ast create mode 100644 coq/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.v create mode 100644 coq/ethereum/spurious_dragon/vm/precompiled_contracts/identity.ast create mode 100644 coq/ethereum/spurious_dragon/vm/precompiled_contracts/identity.v create mode 100644 coq/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.ast create mode 100644 coq/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.v create mode 100644 coq/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.ast create mode 100644 coq/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.v create mode 100644 coq/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.ast create mode 100644 coq/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.v create mode 100644 coq/ethereum/spurious_dragon/vm/runtime.ast create mode 100644 coq/ethereum/spurious_dragon/vm/runtime.v create mode 100644 coq/ethereum/spurious_dragon/vm/stack.ast create mode 100644 coq/ethereum/spurious_dragon/vm/stack.v create mode 100644 coq/ethereum/tangerine_whistle/__init__.ast create mode 100644 coq/ethereum/tangerine_whistle/__init__.v create mode 100644 coq/ethereum/tangerine_whistle/blocks.ast create mode 100644 coq/ethereum/tangerine_whistle/blocks.v create mode 100644 coq/ethereum/tangerine_whistle/bloom.ast create mode 100644 coq/ethereum/tangerine_whistle/bloom.v create mode 100644 coq/ethereum/tangerine_whistle/fork.ast create mode 100644 coq/ethereum/tangerine_whistle/fork.v create mode 100644 coq/ethereum/tangerine_whistle/fork_types.ast create mode 100644 coq/ethereum/tangerine_whistle/fork_types.v create mode 100644 coq/ethereum/tangerine_whistle/state.ast create mode 100644 coq/ethereum/tangerine_whistle/state.v create mode 100644 coq/ethereum/tangerine_whistle/transactions.ast create mode 100644 coq/ethereum/tangerine_whistle/transactions.v create mode 100644 coq/ethereum/tangerine_whistle/trie.ast create mode 100644 coq/ethereum/tangerine_whistle/trie.v create mode 100644 coq/ethereum/tangerine_whistle/utils/__init__.ast create mode 100644 coq/ethereum/tangerine_whistle/utils/__init__.v create mode 100644 coq/ethereum/tangerine_whistle/utils/address.ast create mode 100644 coq/ethereum/tangerine_whistle/utils/address.v create mode 100644 coq/ethereum/tangerine_whistle/utils/hexadecimal.ast create mode 100644 coq/ethereum/tangerine_whistle/utils/hexadecimal.v create mode 100644 coq/ethereum/tangerine_whistle/utils/message.ast create mode 100644 coq/ethereum/tangerine_whistle/utils/message.v create mode 100644 coq/ethereum/tangerine_whistle/vm/__init__.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/__init__.v create mode 100644 coq/ethereum/tangerine_whistle/vm/exceptions.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/exceptions.v create mode 100644 coq/ethereum/tangerine_whistle/vm/gas.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/gas.v create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/__init__.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/__init__.v create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/arithmetic.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/arithmetic.v create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/bitwise.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/bitwise.v create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/block.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/block.v create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/comparison.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/comparison.v create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/control_flow.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/control_flow.v create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/environment.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/environment.v create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/keccak.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/keccak.v create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/log.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/log.v create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/memory.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/memory.v create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/stack.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/stack.v create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/storage.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/storage.v create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/system.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/instructions/system.v create mode 100644 coq/ethereum/tangerine_whistle/vm/interpreter.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/interpreter.v create mode 100644 coq/ethereum/tangerine_whistle/vm/memory.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/memory.v create mode 100644 coq/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.v create mode 100644 coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.v create mode 100644 coq/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.v create mode 100644 coq/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.v create mode 100644 coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.v create mode 100644 coq/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.v create mode 100644 coq/ethereum/tangerine_whistle/vm/runtime.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/runtime.v create mode 100644 coq/ethereum/tangerine_whistle/vm/stack.ast create mode 100644 coq/ethereum/tangerine_whistle/vm/stack.v create mode 100644 coq/ethereum/trace.ast create mode 100644 coq/ethereum/trace.v create mode 100644 coq/ethereum/utils/__init__.ast create mode 100644 coq/ethereum/utils/__init__.v create mode 100644 coq/ethereum/utils/byte.ast create mode 100644 coq/ethereum/utils/byte.v create mode 100644 coq/ethereum/utils/hexadecimal.ast create mode 100644 coq/ethereum/utils/hexadecimal.v create mode 100644 coq/ethereum/utils/numeric.ast create mode 100644 coq/ethereum/utils/numeric.v create mode 100644 coq/ethereum/utils/safe_arithmetic.ast create mode 100644 coq/ethereum/utils/safe_arithmetic.v delete mode 100644 coq/translation/bloom.v delete mode 100644 coq/translation/fork.v delete mode 100644 coq/translation/state.v delete mode 100644 coq/translation/trie.v delete mode 100644 coq/translation/utils/address.v delete mode 100644 coq/translation/utils/hexadecimal.v delete mode 100644 coq/translation/utils/message.v delete mode 100644 coq/translation/vm/__init__.v delete mode 100644 coq/translation/vm/gas.v delete mode 100644 coq/translation/vm/instructions/arithmetic.v delete mode 100644 coq/translation/vm/instructions/bitwise.v delete mode 100644 coq/translation/vm/instructions/block.v delete mode 100644 coq/translation/vm/instructions/comparison.v delete mode 100644 coq/translation/vm/instructions/control_flow.v delete mode 100644 coq/translation/vm/instructions/environment.v delete mode 100644 coq/translation/vm/instructions/keccak.v delete mode 100644 coq/translation/vm/instructions/log.v delete mode 100644 coq/translation/vm/instructions/memory.v delete mode 100644 coq/translation/vm/instructions/stack.v delete mode 100644 coq/translation/vm/instructions/storage.v delete mode 100644 coq/translation/vm/instructions/system.v delete mode 100644 coq/translation/vm/interpreter.v delete mode 100644 coq/translation/vm/memory.v delete mode 100644 coq/translation/vm/precompiled_contracts/alt_bn128.v delete mode 100644 coq/translation/vm/precompiled_contracts/blake2f.v delete mode 100644 coq/translation/vm/precompiled_contracts/ecrecover.v delete mode 100644 coq/translation/vm/precompiled_contracts/identity.v delete mode 100644 coq/translation/vm/precompiled_contracts/mapping.v delete mode 100644 coq/translation/vm/precompiled_contracts/modexp.v delete mode 100644 coq/translation/vm/precompiled_contracts/point_evaluation.v delete mode 100644 coq/translation/vm/precompiled_contracts/ripemd160.v delete mode 100644 coq/translation/vm/precompiled_contracts/sha256.v delete mode 100644 coq/translation/vm/runtime.v delete mode 100644 coq/translation/vm/stack.v 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..66fc97f212 --- /dev/null +++ b/coq/ethereum/__init__.v @@ -0,0 +1,19 @@ +(* +### 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..46596e6954 --- /dev/null +++ b/coq/ethereum/arrow_glacier/__init__.v @@ -0,0 +1,6 @@ +(* +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..1132722431 --- /dev/null +++ b/coq/ethereum/arrow_glacier/blocks.v @@ -0,0 +1,19 @@ +(* +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 ..crypto.hash. +Require arrow_glacier.fork_types. +Require arrow_glacier.transactions. diff --git a/coq/translation/bloom.ast b/coq/ethereum/arrow_glacier/bloom.ast similarity index 100% rename from coq/translation/bloom.ast rename to coq/ethereum/arrow_glacier/bloom.ast diff --git a/coq/ethereum/arrow_glacier/bloom.v b/coq/ethereum/arrow_glacier/bloom.v new file mode 100644 index 0000000000..8549854244 --- /dev/null +++ b/coq/ethereum/arrow_glacier/bloom.v @@ -0,0 +1,66 @@ +(* +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 arrow_glacier.blocks. +Require arrow_glacier.fork_types. + +Definition add_to_bloom : 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. + *) + let* hash := ethereum.crypto.hash.keccak256 (| + bloom_entry + |) in + (* TODO statement *) + + +Definition logs_bloom : M unit := + (* + 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 *) + diff --git a/coq/translation/exceptions.ast b/coq/ethereum/arrow_glacier/exceptions.ast similarity index 100% rename from coq/translation/exceptions.ast rename to coq/ethereum/arrow_glacier/exceptions.ast diff --git a/coq/translation/exceptions.v b/coq/ethereum/arrow_glacier/exceptions.v similarity index 100% rename from coq/translation/exceptions.v rename to coq/ethereum/arrow_glacier/exceptions.v 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..aaced5b610 --- /dev/null +++ b/coq/ethereum/arrow_glacier/fork.v @@ -0,0 +1,847 @@ +(* +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 arrow_glacier.blocks. +Require arrow_glacier.bloom. +Require arrow_glacier.fork_types. +Require arrow_glacier.state. +Require arrow_glacier.transactions. +Require arrow_glacier.trie. +Require arrow_glacier.utils.message. +Require arrow_glacier.vm.interpreter. + +Definition apply_fork : M unit := + (* + 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 *) + + +Definition get_last_256_block_hashes : M unit := + (* + 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. + *) + let* recent_blocks := (* TODO expression *) in + (* TODO statement *) + let* recent_block_hashes := (* TODO expression *) in + (* TODO statement *) + let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *).["header"] + |) + |) in + do* recent_block_hashes.["append"] (| + most_recent_block_hash + |) in + (* TODO statement *) + + +Definition state_transition : 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`. + *) + let* parent_header := (* TODO expression *).["header"] in + do* validate_header (| + block.["header"], + parent_header + |) in + do* validate_ommers (| + block.["ommers"], + block.["header"], + chain + |) in + let* apply_body_output := apply_body (| + chain.["state"], + get_last_256_block_hashes (| + chain + |), + block.["header"].["coinbase"], + block.["header"].["number"], + block.["header"].["base_fee_per_gas"], + block.["header"].["gas_limit"], + block.["header"].["timestamp"], + block.["header"].["difficulty"], + block.["transactions"], + block.["ommers"], + chain.["chain_id"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* chain.["blocks"].["append"] (| + block + |) in + (* TODO statement *) + + +Definition calculate_base_fee_per_gas : M unit := + (* + 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. + *) + let* parent_gas_target := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_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 *) + let* expected_base_fee_per_gas := calculate_base_fee_per_gas (| + header.["gas_limit"], + parent_header.["gas_limit"], + parent_header.["gas_used"], + parent_header.["base_fee_per_gas"] + |) in + (* TODO statement *) + let* parent_has_ommers := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* block_difficulty := calculate_block_difficulty (| + header.["number"], + header.["timestamp"], + parent_header.["timestamp"], + parent_header.["difficulty"], + parent_has_ommers + |) in + (* TODO statement *) + let* block_parent_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + parent_header + |) + |) in + (* TODO statement *) + do* validate_proof_of_work (| + header + |) in + + +Definition generate_header_hash_for_pow : M unit := + (* + 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. + *) + let* header_data_without_pow_artefacts := (* TODO expression *) in + (* TODO statement *) + + +Definition validate_proof_of_work : 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. + *) + let* header_hash := generate_header_hash_for_pow (| + header + |) in + let* cache := ethereum.ethash.generate_cache (| + header.["number"] + |) in + (* TODO assignment *) + (* TODO statement *) + let* limit := (* TODO expression *) in + (* TODO statement *) + + +Definition check_transaction : M unit := + (* + 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 *) + let* sender_address := recover_sender (| + chain_id, + tx + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition make_receipt : M unit := + (* + 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. + *) + let* receipt := blocks.Receipt (| + + |) in + (* TODO statement *) + + +Definition apply_body : M unit := + (* + 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. + *) + let* gas_available := block_gas_limit in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* pay_rewards (| + state, + block_number, + coinbase, + ommers + |) in + let* block_gas_used := (* TODO expression *) in + let* block_logs_bloom := bloom.logs_bloom (| + block_logs + |) in + (* TODO statement *) + + +Definition validate_ommers : 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. + *) + let* block_hash := rlp.["rlp_hash"] (| + block_header + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* ommers_hashes := (* TODO expression *) in + (* TODO statement *) + let* recent_canonical_blocks := (* TODO expression *) in + let* recent_canonical_block_hashes := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition pay_rewards : 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. + *) + let* ommer_count := ethereum_types.numeric.U256 (| + len (| + ommers + |) + |) in + let* miner_reward := (* TODO expression *) in + do* state.create_ether (| + state, + coinbase, + miner_reward + |) in + (* TODO statement *) + + +Definition process_transaction : M unit := + (* + 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 *) + let* sender := env.["origin"] in + let* sender_account := state.get_account (| + env.["state"], + sender + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* effective_gas_fee := (* TODO expression *) in + let* gas := (* TODO expression *) in + do* state.increment_nonce (| + env.["state"], + sender + |) in + let* sender_balance_after_gas_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + ethereum_types.numeric.U256 (| + sender_balance_after_gas_fee + |) + |) in + let* preaccessed_addresses := set (| + + |) in + let* preaccessed_storage_keys := set (| + + |) in + (* TODO statement *) + let* message := utils.message.prepare_message (| + sender, + tx.["to"], + tx.["value"], + tx.["data"], + gas, + env + |) in + let* output := vm.interpreter.process_message_call (| + message, + env + |) in + let* gas_used := (* TODO expression *) in + let* gas_refund := min (| + (* TODO expression *), + ethereum_types.numeric.Uint (| + output.["refund_counter"] + |) + |) in + let* gas_refund_amount := (* TODO expression *) in + let* priority_fee_per_gas := (* TODO expression *) in + let* transaction_fee := (* TODO expression *) in + let* total_gas_used := (* TODO expression *) in + let* sender_balance_after_refund := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + sender_balance_after_refund + |) in + let* coinbase_balance_after_mining_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_transaction : M unit := + (* + 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 *) + + +Definition calculate_intrinsic_cost : M unit := + (* + 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. + *) + let* data_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + let* access_list_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + + +Definition recover_sender : M unit := + (* + 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 *) + + +Definition signing_hash_pre155 : M unit := + (* + 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 *) + + +Definition signing_hash_155 : M unit := + (* + 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 *) + + +Definition signing_hash_2930 : M unit := + (* + 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 *) + + +Definition signing_hash_1559 : M unit := + (* + 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 *) + + +Definition compute_header_hash : M unit := + (* + 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 *) + + +Definition check_gas_limit : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_block_difficulty : M unit := + (* + 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. + *) + let* offset := (* TODO expression *) in + let* difficulty := (* TODO expression *) in + let* num_bomb_periods := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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/translation/fork_types.v b/coq/ethereum/arrow_glacier/fork_types.v similarity index 54% rename from coq/translation/fork_types.v rename to coq/ethereum/arrow_glacier/fork_types.v index f8294e1e51..14de99d5e5 100644 --- a/coq/translation/fork_types.v +++ b/coq/ethereum/arrow_glacier/fork_types.v @@ -16,4 +16,14 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require crypto.hash. +Require ..crypto.hash. + +Definition encode_account : M unit := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + 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..97d1bf908b --- /dev/null +++ b/coq/ethereum/arrow_glacier/state.v @@ -0,0 +1,593 @@ +(* +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 arrow_glacier.fork_types. +Require arrow_glacier.trie. + +Definition close_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 *) + + +Definition begin_transaction : 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* state.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + + +Definition commit_transaction : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* state.["_snapshots"].["pop"] (| + + |) in + (* TODO statement *) + + +Definition rollback_transaction : 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 *) + + +Definition get_account : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition get_account_optional : M unit := + (* + 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. + *) + let* account := trie.trie_get (| + state.["_main_trie"], + address + |) in + (* TODO statement *) + + +Definition set_account : 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 (| + state.["_main_trie"], + address, + account + |) in + + +Definition destroy_account : 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* destroy_storage (| + state, + address + |) in + do* set_account (| + state, + address, + (* TODO expression *) + |) in + + +Definition destroy_storage : 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 *) + + +Definition mark_account_created : 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* state.["created_accounts"].["add"] (| + address + |) in + + +Definition get_storage : M unit := + (* + 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. + *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_storage : 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 *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition storage_root : M unit := + (* + 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 *) + + +Definition state_root : M unit := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition account_exists : M unit := + (* + 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 *) + + +Definition account_has_code_or_nonce : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_empty : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition account_exists_and_is_empty : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_alive : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition modify_state : M unit := + (* + Modify an `Account` in the `State`. + *) + do* set_account (| + state, + address, + ethereum_types.frozen.modify (| + get_account (| + state, + address + |), + f + |) + |) in + + +Definition move_ether : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* modify_state (| + state, + sender_address, + reduce_sender_balance + |) in + do* modify_state (| + state, + recipient_address, + increase_recipient_balance + |) in + + +Definition set_account_balance : 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* modify_state (| + state, + address, + set_balance + |) in + + +Definition touch_account : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + + +Definition increment_nonce : 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* modify_state (| + state, + address, + increase_nonce + |) in + + +Definition set_code : 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* modify_state (| + state, + address, + write_code + |) in + + +Definition create_ether : 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* modify_state (| + state, + address, + increase_balance + |) in + + +Definition get_storage_original : M unit := + (* + 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 *) + let* original_account_trie := original_trie.["get"] (| + address + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + 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..f270c148f2 --- /dev/null +++ b/coq/ethereum/arrow_glacier/transactions.v @@ -0,0 +1,27 @@ +(* +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 arrow_glacier.exceptions. +Require arrow_glacier.fork_types. + +Definition encode_transaction : M unit := + (* + Encode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + + +Definition decode_transaction : M unit := + (* + Decode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + 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..548de91e1c --- /dev/null +++ b/coq/ethereum/arrow_glacier/trie.v @@ -0,0 +1,274 @@ +(* +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 : M unit := + (* + 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 *) + let* encoded := rlp.["encode"] (| + unencoded + |) in + (* TODO statement *) + + +Definition encode_node : M unit := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + + +Definition copy_trie : M unit := + (* + 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 *) + + +Definition trie_set : 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 *) + + +Definition trie_get : M unit := + (* + 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 *) + + +Definition common_prefix_length : M unit := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition nibble_list_to_compact : M unit := + (* + 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. + *) + let* compact := bytearray (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_nibble_list : M unit := + (* + 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. + *) + let* nibble_list := bytearray (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _prepare_trie : M unit := + (* + 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 *) + + +Definition root : M unit := + (* + 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. + *) + let* obj := _prepare_trie (| + trie, + get_storage_root + |) in + let* root_node := encode_internal_node (| + patricialize (| + obj, + Uint (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + + +Definition patricialize : M unit := + (* + 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 *) + let* arbitrary_key := next (| + iter (| + obj + |) + |) in + (* TODO statement *) + let* substring := (* TODO expression *) in + let* prefix_length := len (| + substring + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + diff --git a/coq/translation/utils/__init__.ast b/coq/ethereum/arrow_glacier/utils/__init__.ast similarity index 100% rename from coq/translation/utils/__init__.ast rename to coq/ethereum/arrow_glacier/utils/__init__.ast diff --git a/coq/translation/utils/__init__.v b/coq/ethereum/arrow_glacier/utils/__init__.v similarity index 100% rename from coq/translation/utils/__init__.v rename to coq/ethereum/arrow_glacier/utils/__init__.v 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..08514e27df --- /dev/null +++ b/coq/ethereum/arrow_glacier/utils/address.v @@ -0,0 +1,99 @@ +(* +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 arrow_glacier.fork_types. + +Definition to_address : M unit := + (* + 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 *) + + +Definition compute_contract_address : M unit := + (* + 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. + *) + let* computed_address := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *) + |) + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition compute_create2_contract_address : M unit := + (* + 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. + *) + let* preimage := (* TODO expression *) in + let* computed_address := ethereum.crypto.hash.keccak256 (| + preimage + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + 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..1ac7f475c4 --- /dev/null +++ b/coq/ethereum/arrow_glacier/utils/hexadecimal.v @@ -0,0 +1,68 @@ +(* +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 arrow_glacier.fork_types. + +Definition hex_to_root : M unit := + (* + 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 *) + + +Definition hex_to_bloom : M unit := + (* + 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 *) + + +Definition hex_to_address : M unit := + (* + 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 *) + 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..44807f2118 --- /dev/null +++ b/coq/ethereum/arrow_glacier/utils/message.v @@ -0,0 +1,82 @@ +(* +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 arrow_glacier.fork_types. +Require arrow_glacier.state. +Require arrow_glacier.vm. +Require arrow_glacier.vm.precompiled_contracts.mapping. +Require arrow_glacier.utils.address. + +Definition prepare_message : M unit := + (* + 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 *) + let* accessed_addresses := set (| + + |) in + do* accessed_addresses.["add"] (| + current_target + |) in + do* accessed_addresses.["add"] (| + caller + |) in + do* accessed_addresses.["update"] (| + vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS.["keys"] (| + + |) + |) in + do* accessed_addresses.["update"] (| + preaccessed_addresses + |) in + (* TODO statement *) + 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..4275b0cf57 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/__init__.v @@ -0,0 +1,69 @@ +(* +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 arrow_glacier.blocks. +Require arrow_glacier.fork_types. +Require arrow_glacier.state. +Require arrow_glacier.vm.precompiled_contracts. + +Definition incorporate_child_on_success : 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* evm.["accounts_to_delete"].["update"] (| + child_evm.["accounts_to_delete"] + |) in + do* evm.["touched_accounts"].["update"] (| + child_evm.["touched_accounts"] + |) in + (* TODO statement *) + do* evm.["accessed_addresses"].["update"] (| + child_evm.["accessed_addresses"] + |) in + do* evm.["accessed_storage_keys"].["update"] (| + child_evm.["accessed_storage_keys"] + |) in + + +Definition incorporate_child_on_error : 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 *) + (* TODO statement *) + 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/translation/vm/exceptions.v b/coq/ethereum/arrow_glacier/vm/exceptions.v similarity index 100% rename from coq/translation/vm/exceptions.v rename to coq/ethereum/arrow_glacier/vm/exceptions.v 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..2c6dcc12e1 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/gas.v @@ -0,0 +1,151 @@ +(* +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 arrow_glacier.vm.exceptions. + +Definition charge_gas : 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 (| + int (| + amount + |) + |) + |) in + (* TODO statement *) + + +Definition calculate_memory_gas_cost : M unit := + (* + 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. + *) + let* size_in_words := (* TODO expression *) in + let* linear_cost := (* TODO expression *) in + let* quadratic_cost := (* TODO expression *) in + let* total_gas_cost := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_gas_extend_memory : M unit := + (* + 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` + *) + let* size_to_extend := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* to_be_paid := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* current_size := ethereum_types.numeric.Uint (| + len (| + memory + |) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_message_call_gas : M unit := + (* + 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` + *) + let* call_stipend := (* TODO expression *) in + (* TODO statement *) + let* gas := min (| + gas, + max_message_call_gas (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + + +Definition max_message_call_gas : M unit := + (* + 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 *) + 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/translation/vm/instructions/__init__.v b/coq/ethereum/arrow_glacier/vm/instructions/__init__.v similarity index 94% rename from coq/translation/vm/instructions/__init__.v rename to coq/ethereum/arrow_glacier/vm/instructions/__init__.v index 8a859b1645..b36b1ebfef 100644 --- a/coq/translation/vm/instructions/__init__.v +++ b/coq/ethereum/arrow_glacier/vm/instructions/__init__.v @@ -13,4 +13,3 @@ Machine readable representations of EVM instructions, and a mapping to their implementations. *) -Require typing. diff --git a/coq/translation/vm/instructions/arithmetic.ast b/coq/ethereum/arrow_glacier/vm/instructions/arithmetic.ast similarity index 100% rename from coq/translation/vm/instructions/arithmetic.ast rename to coq/ethereum/arrow_glacier/vm/instructions/arithmetic.ast 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..44588d8277 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/arithmetic.v @@ -0,0 +1,387 @@ +(* +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 arrow_glacier.vm.gas. +Require arrow_glacier.vm.stack. + +Definition add : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_add"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition sub : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_sub"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mul : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + let* result := x.["wrapping_mul"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition div : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |) in + let* divisor := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + quotient + |) in + (* TODO statement *) + + +Definition sdiv : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* divisor := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + quotient + |) + |) in + (* TODO statement *) + + +Definition mod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + remainder + |) in + (* TODO statement *) + + +Definition smod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* y := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + remainder + |) + |) in + (* TODO statement *) + + +Definition addmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mulmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition exp : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* base := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent_bits := exponent.["bit_length"] (| + + |) in + let* exponent_bytes := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* result := ethereum_types.numeric.U256 (| + pow (| + base, + exponent, + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signextend : 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. + + *) + let* byte_num := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + diff --git a/coq/translation/vm/instructions/bitwise.ast b/coq/ethereum/arrow_glacier/vm/instructions/bitwise.ast similarity index 100% rename from coq/translation/vm/instructions/bitwise.ast rename to coq/ethereum/arrow_glacier/vm/instructions/bitwise.ast 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..c95b791002 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/bitwise.v @@ -0,0 +1,245 @@ +(* +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 arrow_glacier.vm.gas. +Require arrow_glacier.vm.stack. + +Definition bitwise_and : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_or : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_xor : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_not : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition get_byte : 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. + + *) + let* byte_index := stack.pop (| + evm.["stack"] + |) in + let* word := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shl : 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. + *) + let* shift := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shr : 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. + *) + let* shift := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_sar : 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. + *) + let* shift := int (| + stack.pop (| + evm.["stack"] + |) + |) in + let* signed_value := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..07dafe617e --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/block.v @@ -0,0 +1,207 @@ +(* +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 arrow_glacier.vm.gas. +Require arrow_glacier.vm.stack. + +Definition block_hash : 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. + + *) + let* block_number := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOCK_HASH + |) in + let* max_block_number := (* TODO expression *) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + + +Definition coinbase : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["coinbase"] + |) + |) in + (* TODO statement *) + + +Definition timestamp : 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 (| + evm.["stack"], + evm.["env"].["time"] + |) in + (* TODO statement *) + + +Definition number : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["number"] + |) + |) in + (* TODO statement *) + + +Definition difficulty : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["difficulty"] + |) + |) in + (* TODO statement *) + + +Definition gas_limit : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_limit"] + |) + |) in + (* TODO statement *) + + +Definition chain_id : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["chain_id"] + |) + |) in + (* TODO statement *) + diff --git a/coq/translation/vm/instructions/comparison.ast b/coq/ethereum/arrow_glacier/vm/instructions/comparison.ast similarity index 100% rename from coq/translation/vm/instructions/comparison.ast rename to coq/ethereum/arrow_glacier/vm/instructions/comparison.ast 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..e7f58b64d4 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/comparison.v @@ -0,0 +1,206 @@ +(* +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 arrow_glacier.vm.gas. +Require arrow_glacier.vm.stack. + +Definition less_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_less_than : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition greater_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_greater_than : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition equal : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition is_zero : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + diff --git a/coq/translation/vm/instructions/control_flow.ast b/coq/ethereum/arrow_glacier/vm/instructions/control_flow.ast similarity index 100% rename from coq/translation/vm/instructions/control_flow.ast rename to coq/ethereum/arrow_glacier/vm/instructions/control_flow.ast 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..30741eb3aa --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/control_flow.v @@ -0,0 +1,156 @@ +(* +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 arrow_glacier.vm.gas. +Require arrow_glacier.vm.exceptions. +Require arrow_glacier.vm.stack. + +Definition stop : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition jump : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_MID + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition jumpi : 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. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* conditional_value := stack.pop (| + evm.["stack"] + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_HIGH + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition pc : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["pc"] + |) + |) in + (* TODO statement *) + + +Definition gas_left : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + + +Definition jumpdest : 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 *) + (* TODO statement *) + 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..005e9ec07f --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/environment.v @@ -0,0 +1,568 @@ +(* +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 arrow_glacier.fork_types. +Require arrow_glacier.state. +Require arrow_glacier.utils.address. +Require arrow_glacier.vm.memory. +Require arrow_glacier.vm.exceptions. +Require arrow_glacier.vm.gas. +Require arrow_glacier.vm.stack. + +Definition address : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["current_target"] + |) + |) in + (* TODO statement *) + + +Definition balance : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* balance := state.get_account (| + evm.["env"].["state"], + address + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition origin : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["origin"] + |) + |) in + (* TODO statement *) + + +Definition caller : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["caller"] + |) + |) in + (* TODO statement *) + + +Definition callvalue : 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 (| + evm.["stack"], + evm.["message"].["value"] + |) in + (* TODO statement *) + + +Definition calldataload : 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. + + *) + let* start_index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + start_index, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + value + |) + |) in + (* TODO statement *) + + +Definition calldatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["message"].["data"] + |) + |) + |) in + (* TODO statement *) + + +Definition calldatacopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* data_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + data_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition codesize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["code"] + |) + |) + |) in + (* TODO statement *) + + +Definition codecopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["code"], + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition gasprice : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_price"] + |) + |) in + (* TODO statement *) + + +Definition extcodesize : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* codesize := ethereum_types.numeric.U256 (| + len (| + state.get_account (| + evm.["env"].["state"], + address + |).["code"] + |) + |) in + do* stack.push (| + evm.["stack"], + codesize + |) in + (* TODO statement *) + + +Definition extcodecopy : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* code := state.get_account (| + evm.["env"].["state"], + address + |).["code"] in + let* value := vm.memory.buffer_read (| + code, + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition returndatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["return_data"] + |) + |) + |) in + (* TODO statement *) + + +Definition returndatacopy : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* return_data_start_position := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition extcodehash : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* account := state.get_account (| + evm.["env"].["state"], + address + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + codehash + |) in + (* TODO statement *) + + +Definition self_balance : 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 + let* balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition base_fee : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["base_fee_per_gas"] + |) + |) in + (* TODO statement *) + diff --git a/coq/translation/vm/instructions/keccak.ast b/coq/ethereum/arrow_glacier/vm/instructions/keccak.ast similarity index 100% rename from coq/translation/vm/instructions/keccak.ast rename to coq/ethereum/arrow_glacier/vm/instructions/keccak.ast 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..e0f701b3b3 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/keccak.v @@ -0,0 +1,67 @@ +(* +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 arrow_glacier.vm.gas. +Require arrow_glacier.vm.memory. +Require arrow_glacier.vm.stack. + +Definition keccak : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* word_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + let* hash := ethereum.crypto.hash.keccak256 (| + data + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + diff --git a/coq/translation/vm/instructions/log.ast b/coq/ethereum/arrow_glacier/vm/instructions/log.ast similarity index 100% rename from coq/translation/vm/instructions/log.ast rename to coq/ethereum/arrow_glacier/vm/instructions/log.ast 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..cba7bd19e9 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/log.v @@ -0,0 +1,61 @@ +(* +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 arrow_glacier.blocks. +Require arrow_glacier.vm.exceptions. +Require arrow_glacier.vm.gas. +Require arrow_glacier.vm.memory. +Require arrow_glacier.vm.stack. + +Definition log_n : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* topics := (* TODO expression *) in + (* TODO statement *) + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* log_entry := blocks.Log (| + + |) in + (* TODO assignment *) + (* TODO statement *) + 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..7dfeefbd5a --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/memory.v @@ -0,0 +1,158 @@ +(* +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 arrow_glacier.vm.gas. +Require arrow_glacier.vm.memory. +Require arrow_glacier.vm.stack. + +Definition mstore : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* memory.memory_write (| + evm.["memory"], + start_position, + value + |) in + (* TODO statement *) + + +Definition mstore8 : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + (* TODO expression *) + |) in + do* memory.memory_write (| + evm.["memory"], + start_position, + normalized_bytes_value + |) in + (* TODO statement *) + + +Definition mload : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.memory_read_bytes (| + evm.["memory"], + start_position, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition msize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["memory"] + |) + |) + |) in + (* TODO statement *) + 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..e2e7b545a9 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/stack.v @@ -0,0 +1,133 @@ +(* +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 arrow_glacier.vm.exceptions. +Require arrow_glacier.vm.gas. +Require arrow_glacier.vm.memory. + +Definition pop : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* stack.["pop"] (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BASE + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition push_n : 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 + let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + evm.["code"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + num_bytes + |) + |) + |) in + do* stack.["push"] (| + evm.["stack"], + data_to_push + |) in + (* TODO statement *) + + +Definition dup_n : 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 *) + let* data_to_duplicate := (* TODO expression *) in + do* stack.["push"] (| + evm.["stack"], + data_to_duplicate + |) in + (* TODO statement *) + + +Definition swap_n : 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 *) + (* TODO statement *) + 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..fe286beabf --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/storage.v @@ -0,0 +1,97 @@ +(* +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 arrow_glacier.state. +Require arrow_glacier.vm.exceptions. +Require arrow_glacier.vm.gas. +Require arrow_glacier.vm.stack. + +Definition sload : 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. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + (* TODO statement *) + let* value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition sstore : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + (* TODO statement *) + let* original_value := state.get_storage_original (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + let* current_value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + let* gas_cost := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + do* state.set_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + 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..6ea0d1e6bc --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/system.v @@ -0,0 +1,585 @@ +(* +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 arrow_glacier.fork_types. +Require arrow_glacier.state. +Require arrow_glacier.utils.address. +Require arrow_glacier.vm.exceptions. +Require arrow_glacier.vm.gas. +Require arrow_glacier.vm.memory. +Require arrow_glacier.vm.stack. + +Definition generic_create : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + do* evm.["accessed_addresses"].["add"] (| + contract_address + |) in + let* create_message_gas := gas.max_message_call_gas (| + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + let* sender_address := evm.["message"].["current_target"] in + let* sender := state.get_account (| + evm.["env"].["state"], + sender_address + |) in + (* TODO statement *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) in + do* state.increment_nonce (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |) in + let* child_message := Message (| + + |) in + let* child_evm := process_create_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + + +Definition create : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_contract_address (| + evm.["message"].["current_target"], + state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["nonce"] + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size + |) in + (* TODO statement *) + + +Definition create2 : 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. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* salt := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* call_data_words := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_create2_contract_address (| + evm.["message"].["current_target"], + salt, + memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size + |) in + (* TODO statement *) + + +Definition return_ : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + + +Definition generic_call : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_input_start_position, + memory_input_size + |) in + let* code := state.get_account (| + evm.["env"].["state"], + code_address + |).["code"] in + let* child_message := Message (| + + |) in + let* child_evm := process_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + let* actual_output_size := min (| + memory_output_size, + ethereum_types.numeric.U256 (| + len (| + child_evm.["output"] + |) + |) + |) in + do* memory.memory_write (| + evm.["memory"], + memory_output_start_position, + (* TODO expression *) + |) in + + +Definition call : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* create_gas_cost := (* TODO expression *) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition callcode : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* to := evm.["message"].["current_target"] in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition selfdestruct : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* beneficiary := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* gas_cost := gas.GAS_SELF_DESTRUCT in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + let* originator := evm.["message"].["current_target"] in + let* beneficiary_balance := state.get_account (| + evm.["env"].["state"], + beneficiary + |).["balance"] in + let* originator_balance := state.get_account (| + evm.["env"].["state"], + originator + |).["balance"] in + do* state.set_account_balance (| + evm.["env"].["state"], + beneficiary, + (* TODO expression *) + |) in + do* state.set_account_balance (| + evm.["env"].["state"], + originator, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* evm.["accounts_to_delete"].["add"] (| + originator + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition delegatecall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + access_gas_cost + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + evm.["message"].["value"], + evm.["message"].["caller"], + evm.["message"].["current_target"], + code_address, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition staticcall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + access_gas_cost + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + evm.["message"].["current_target"], + to, + to, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition revert : 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. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + extend_memory.["cost"] + |) in + (* TODO statement *) + let* output := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + 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..926ba43393 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/interpreter.v @@ -0,0 +1,159 @@ +(* +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 arrow_glacier.blocks. +Require arrow_glacier.fork_types. +Require arrow_glacier.state. +Require arrow_glacier.vm. +Require arrow_glacier.vm.gas. +Require arrow_glacier.vm.precompiled_contracts.mapping. +Require arrow_glacier.vm.exceptions. +Require arrow_glacier.vm.instructions. +Require arrow_glacier.vm.runtime. + +Definition process_message_call : M unit := + (* + 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 *) + let* tx_end := ethereum.trace.TransactionEnd (| + (* TODO expression *), + evm.["output"], + evm.["error"] + |) in + do* ethereum.trace.evm_trace (| + evm, + tx_end + |) in + (* TODO statement *) + + +Definition process_create_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.destroy_storage (| + env.["state"], + message.["current_target"] + |) in + do* state.mark_account_created (| + env.["state"], + message.["current_target"] + |) in + do* state.increment_nonce (| + env.["state"], + message.["current_target"] + |) in + let* evm := process_message (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.touch_account (| + env.["state"], + message.["current_target"] + |) in + (* TODO statement *) + let* evm := execute_code (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition execute_code : M unit := + (* + 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 + *) + let* code := message.["code"] in + let* valid_jump_destinations := runtime.get_valid_jump_destinations (| + code + |) in + let* evm := Evm (| + + |) in + (* TODO statement *) + (* TODO statement *) + diff --git a/coq/translation/vm/memory.ast b/coq/ethereum/arrow_glacier/vm/memory.ast similarity index 100% rename from coq/translation/vm/memory.ast rename to coq/ethereum/arrow_glacier/vm/memory.ast diff --git a/coq/ethereum/arrow_glacier/vm/memory.v b/coq/ethereum/arrow_glacier/vm/memory.v new file mode 100644 index 0000000000..94b6a44639 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/memory.v @@ -0,0 +1,75 @@ +(* +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 : 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 *) + + +Definition memory_read_bytes : M unit := + (* + 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 *) + + +Definition buffer_read : M unit := + (* + 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 *) + 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..065fa245fc --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.v @@ -0,0 +1,16 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require arrow_glacier.utils.hexadecimal. diff --git a/coq/translation/vm/precompiled_contracts/alt_bn128.ast b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.ast similarity index 100% rename from coq/translation/vm/precompiled_contracts/alt_bn128.ast rename to coq/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.ast 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..dae5e63069 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,187 @@ +(* +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 arrow_glacier.vm. +Require arrow_glacier.vm.gas. +Require arrow_glacier.vm.memory. +Require arrow_glacier.vm.exceptions. + +Definition alt_bn128_add : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* x1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x1_bytes + |) + |) in + let* y1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y1_bytes + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := (* TODO expression *) in + (* TODO assignment *) + + +Definition alt_bn128_mul : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* n := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := p0.["mul_by"] (| + n + |) in + (* TODO assignment *) + + +Definition alt_bn128_pairing_check : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + diff --git a/coq/translation/vm/precompiled_contracts/blake2f.ast b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.ast similarity index 100% rename from coq/translation/vm/precompiled_contracts/blake2f.ast rename to coq/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.ast 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..f5e7a7d04d --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,41 @@ +(* +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 arrow_glacier.vm. +Require arrow_glacier.vm.gas. +Require arrow_glacier.vm.exceptions. + +Definition blake2f : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + (* TODO statement *) + let* blake2b := ethereum.crypto.blake2.Blake2b (| + + |) in + (* TODO assignment *) + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + diff --git a/coq/translation/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.ast similarity index 100% rename from coq/translation/vm/precompiled_contracts/ecrecover.ast rename to coq/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.ast 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..d76f2ac095 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,93 @@ +(* +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 arrow_glacier.vm. +Require arrow_glacier.vm.gas. +Require arrow_glacier.vm.memory. + +Definition ecrecover : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_ECRECOVER + |) in + let* message_hash_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* message_hash := ethereum.crypto.hash.Hash32 (| + message_hash_bytes + |) in + let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + address, + (* TODO expression *) + |) in + (* TODO assignment *) + diff --git a/coq/translation/vm/precompiled_contracts/identity.ast b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/identity.ast similarity index 100% rename from coq/translation/vm/precompiled_contracts/identity.ast rename to coq/ethereum/arrow_glacier/vm/precompiled_contracts/identity.ast 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..d05dadd70e --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/identity.v @@ -0,0 +1,36 @@ +(* +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 arrow_glacier.vm. +Require arrow_glacier.vm.gas. + +Definition identity : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..94773a3daf --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.v @@ -0,0 +1,23 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require arrow_glacier.fork_types. +Require arrow_glacier.vm.precompiled_contracts.alt_bn128. +Require arrow_glacier.vm.precompiled_contracts.blake2f. +Require arrow_glacier.vm.precompiled_contracts.ecrecover. +Require arrow_glacier.vm.precompiled_contracts.identity. +Require arrow_glacier.vm.precompiled_contracts.modexp. +Require arrow_glacier.vm.precompiled_contracts.ripemd160. +Require arrow_glacier.vm.precompiled_contracts.sha256. diff --git a/coq/translation/vm/precompiled_contracts/modexp.ast b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.ast similarity index 100% rename from coq/translation/vm/precompiled_contracts/modexp.ast rename to coq/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.ast 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..1ee6b3fa6d --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.v @@ -0,0 +1,203 @@ +(* +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 arrow_glacier.vm. +Require arrow_glacier.vm.gas. +Require arrow_glacier.vm.memory. + +Definition modexp : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + let* data := evm.["message"].["data"] in + let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_start := (* TODO expression *) in + let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + min (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + exp_length + |) + |) + |) in + do* vm.gas.charge_gas (| + evm, + gas_cost (| + base_length, + modulus_length, + exp_length, + exp_head + |) + |) in + (* TODO statement *) + let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + base_length + |) + |) in + let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + exp_length + |) + |) in + let* modulus_start := (* TODO expression *) in + let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + modulus_start, + modulus_length + |) + |) in + (* TODO statement *) + + +Definition complexity : M unit := + (* + 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. + *) + let* max_length := max (| + ethereum_types.numeric.Uint (| + base_length + |), + ethereum_types.numeric.Uint (| + modulus_length + |) + |) in + let* words := (* TODO expression *) in + (* TODO statement *) + + +Definition iterations : M unit := + (* + 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 *) + + +Definition gas_cost : M unit := + (* + 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. + *) + let* multiplication_complexity := complexity (| + base_length, + modulus_length + |) in + let* iteration_count := iterations (| + exponent_length, + exponent_head + |) in + let* cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + diff --git a/coq/translation/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.ast similarity index 100% rename from coq/translation/vm/precompiled_contracts/ripemd160.ast rename to coq/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.ast 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..bc5e73dd3c --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,42 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + let* hash_bytes := hashlib.["new"] (| + (* TODO expression *), + data + |).["digest"] (| + + |) in + let* padded_hash := left_pad_zero_bytes (| + hash_bytes, + (* TODO expression *) + |) in + (* TODO assignment *) + diff --git a/coq/translation/vm/precompiled_contracts/sha256.ast b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.ast similarity index 100% rename from coq/translation/vm/precompiled_contracts/sha256.ast rename to coq/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.ast 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..da6972d411 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.v @@ -0,0 +1,32 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + diff --git a/coq/translation/vm/runtime.ast b/coq/ethereum/arrow_glacier/vm/runtime.ast similarity index 100% rename from coq/translation/vm/runtime.ast rename to coq/ethereum/arrow_glacier/vm/runtime.ast diff --git a/coq/ethereum/arrow_glacier/vm/runtime.v b/coq/ethereum/arrow_glacier/vm/runtime.v new file mode 100644 index 0000000000..03107cd8d3 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/runtime.v @@ -0,0 +1,49 @@ +(* +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 arrow_glacier.vm.instructions. + +Definition get_valid_jump_destinations : M unit := + (* + 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. + *) + let* valid_jump_destinations := set (| + + |) in + let* pc := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + diff --git a/coq/translation/vm/stack.ast b/coq/ethereum/arrow_glacier/vm/stack.ast similarity index 100% rename from coq/translation/vm/stack.ast rename to coq/ethereum/arrow_glacier/vm/stack.ast diff --git a/coq/ethereum/arrow_glacier/vm/stack.v b/coq/ethereum/arrow_glacier/vm/stack.v new file mode 100644 index 0000000000..c58d560b13 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/stack.v @@ -0,0 +1,53 @@ +(* +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 arrow_glacier.vm.exceptions. + +Definition pop : M unit := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + + +Definition push : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + 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..1559435fd6 --- /dev/null +++ b/coq/ethereum/berlin/__init__.v @@ -0,0 +1,7 @@ +(* +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..718999995d --- /dev/null +++ b/coq/ethereum/berlin/blocks.v @@ -0,0 +1,19 @@ +(* +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 ..crypto.hash. +Require berlin.fork_types. +Require 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..e37d9e9866 --- /dev/null +++ b/coq/ethereum/berlin/bloom.v @@ -0,0 +1,66 @@ +(* +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 berlin.blocks. +Require berlin.fork_types. + +Definition add_to_bloom : 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. + *) + let* hash := ethereum.crypto.hash.keccak256 (| + bloom_entry + |) in + (* TODO statement *) + + +Definition logs_bloom : M unit := + (* + 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 *) + 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..137ea143f6 --- /dev/null +++ b/coq/ethereum/berlin/exceptions.v @@ -0,0 +1,6 @@ +(* +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..7225636763 --- /dev/null +++ b/coq/ethereum/berlin/fork.v @@ -0,0 +1,786 @@ +(* +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 berlin.blocks. +Require berlin.bloom. +Require berlin.fork_types. +Require berlin.state. +Require berlin.transactions. +Require berlin.trie. +Require berlin.utils.message. +Require berlin.vm.interpreter. + +Definition apply_fork : M unit := + (* + 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 *) + + +Definition get_last_256_block_hashes : M unit := + (* + 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. + *) + let* recent_blocks := (* TODO expression *) in + (* TODO statement *) + let* recent_block_hashes := (* TODO expression *) in + (* TODO statement *) + let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *).["header"] + |) + |) in + do* recent_block_hashes.["append"] (| + most_recent_block_hash + |) in + (* TODO statement *) + + +Definition state_transition : 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`. + *) + let* parent_header := (* TODO expression *).["header"] in + do* validate_header (| + block.["header"], + parent_header + |) in + do* validate_ommers (| + block.["ommers"], + block.["header"], + chain + |) in + let* apply_body_output := apply_body (| + chain.["state"], + get_last_256_block_hashes (| + chain + |), + block.["header"].["coinbase"], + block.["header"].["number"], + block.["header"].["gas_limit"], + block.["header"].["timestamp"], + block.["header"].["difficulty"], + block.["transactions"], + block.["ommers"], + chain.["chain_id"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* chain.["blocks"].["append"] (| + block + |) in + (* TODO statement *) + + +Definition validate_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 + *) + let* parent_has_ommers := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* block_difficulty := calculate_block_difficulty (| + header.["number"], + header.["timestamp"], + parent_header.["timestamp"], + parent_header.["difficulty"], + parent_has_ommers + |) in + (* TODO statement *) + let* block_parent_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + parent_header + |) + |) in + (* TODO statement *) + do* validate_proof_of_work (| + header + |) in + + +Definition generate_header_hash_for_pow : M unit := + (* + 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. + *) + let* header_data_without_pow_artefacts := (* TODO expression *) in + (* TODO statement *) + + +Definition validate_proof_of_work : 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. + *) + let* header_hash := generate_header_hash_for_pow (| + header + |) in + let* cache := ethereum.ethash.generate_cache (| + header.["number"] + |) in + (* TODO assignment *) + (* TODO statement *) + let* limit := (* TODO expression *) in + (* TODO statement *) + + +Definition check_transaction : M unit := + (* + 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 *) + let* sender_address := recover_sender (| + chain_id, + tx + |) in + (* TODO statement *) + + +Definition make_receipt : M unit := + (* + 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. + *) + let* receipt := blocks.Receipt (| + + |) in + (* TODO statement *) + + +Definition apply_body : M unit := + (* + 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. + *) + let* gas_available := block_gas_limit in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* pay_rewards (| + state, + block_number, + coinbase, + ommers + |) in + let* block_gas_used := (* TODO expression *) in + let* block_logs_bloom := bloom.logs_bloom (| + block_logs + |) in + (* TODO statement *) + + +Definition validate_ommers : 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. + *) + let* block_hash := rlp.["rlp_hash"] (| + block_header + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* ommers_hashes := (* TODO expression *) in + (* TODO statement *) + let* recent_canonical_blocks := (* TODO expression *) in + let* recent_canonical_block_hashes := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition pay_rewards : 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. + *) + let* ommer_count := ethereum_types.numeric.U256 (| + len (| + ommers + |) + |) in + let* miner_reward := (* TODO expression *) in + do* state.create_ether (| + state, + coinbase, + miner_reward + |) in + (* TODO statement *) + + +Definition process_transaction : M unit := + (* + 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 *) + let* sender := env.["origin"] in + let* sender_account := state.get_account (| + env.["state"], + sender + |) in + let* gas_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* gas := (* TODO expression *) in + do* state.increment_nonce (| + env.["state"], + sender + |) in + let* sender_balance_after_gas_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + ethereum_types.numeric.U256 (| + sender_balance_after_gas_fee + |) + |) in + let* preaccessed_addresses := set (| + + |) in + let* preaccessed_storage_keys := set (| + + |) in + (* TODO statement *) + let* message := utils.message.prepare_message (| + sender, + tx.["to"], + tx.["value"], + tx.["data"], + gas, + env + |) in + let* output := vm.interpreter.process_message_call (| + message, + env + |) in + let* gas_used := (* TODO expression *) in + let* gas_refund := min (| + (* TODO expression *), + ethereum_types.numeric.Uint (| + output.["refund_counter"] + |) + |) in + let* gas_refund_amount := (* TODO expression *) in + let* transaction_fee := (* TODO expression *) in + let* total_gas_used := (* TODO expression *) in + let* sender_balance_after_refund := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + sender_balance_after_refund + |) in + let* coinbase_balance_after_mining_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_transaction : M unit := + (* + 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 *) + + +Definition calculate_intrinsic_cost : M unit := + (* + 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. + *) + let* data_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + let* access_list_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + + +Definition recover_sender : M unit := + (* + 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 *) + + +Definition signing_hash_pre155 : M unit := + (* + 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 *) + + +Definition signing_hash_155 : M unit := + (* + 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 *) + + +Definition signing_hash_2930 : M unit := + (* + 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 *) + + +Definition compute_header_hash : M unit := + (* + 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 *) + + +Definition check_gas_limit : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_block_difficulty : M unit := + (* + 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. + *) + let* offset := (* TODO expression *) in + let* difficulty := (* TODO expression *) in + let* num_bomb_periods := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..14de99d5e5 --- /dev/null +++ b/coq/ethereum/berlin/fork_types.v @@ -0,0 +1,29 @@ +(* +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 ..crypto.hash. + +Definition encode_account : M unit := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + 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..34ee56c18a --- /dev/null +++ b/coq/ethereum/berlin/state.v @@ -0,0 +1,593 @@ +(* +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 berlin.fork_types. +Require berlin.trie. + +Definition close_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 *) + + +Definition begin_transaction : 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* state.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + + +Definition commit_transaction : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* state.["_snapshots"].["pop"] (| + + |) in + (* TODO statement *) + + +Definition rollback_transaction : 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 *) + + +Definition get_account : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition get_account_optional : M unit := + (* + 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. + *) + let* account := trie.trie_get (| + state.["_main_trie"], + address + |) in + (* TODO statement *) + + +Definition set_account : 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 (| + state.["_main_trie"], + address, + account + |) in + + +Definition destroy_account : 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* destroy_storage (| + state, + address + |) in + do* set_account (| + state, + address, + (* TODO expression *) + |) in + + +Definition destroy_storage : 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 *) + + +Definition mark_account_created : 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* state.["created_accounts"].["add"] (| + address + |) in + + +Definition get_storage : M unit := + (* + 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. + *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_storage : 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 *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition storage_root : M unit := + (* + 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 *) + + +Definition state_root : M unit := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition account_exists : M unit := + (* + 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 *) + + +Definition account_has_code_or_nonce : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_empty : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition account_exists_and_is_empty : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_alive : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition modify_state : M unit := + (* + Modify an `Account` in the `State`. + *) + do* set_account (| + state, + address, + ethereum_types.frozen.modify (| + get_account (| + state, + address + |), + f + |) + |) in + + +Definition move_ether : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* modify_state (| + state, + sender_address, + reduce_sender_balance + |) in + do* modify_state (| + state, + recipient_address, + increase_recipient_balance + |) in + + +Definition set_account_balance : 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* modify_state (| + state, + address, + set_balance + |) in + + +Definition touch_account : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + + +Definition increment_nonce : 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* modify_state (| + state, + address, + increase_nonce + |) in + + +Definition set_code : 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* modify_state (| + state, + address, + write_code + |) in + + +Definition create_ether : 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* modify_state (| + state, + address, + increase_balance + |) in + + +Definition get_storage_original : M unit := + (* + 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 *) + let* original_account_trie := original_trie.["get"] (| + address + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + 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..18237477b5 --- /dev/null +++ b/coq/ethereum/berlin/transactions.v @@ -0,0 +1,27 @@ +(* +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 berlin.exceptions. +Require berlin.fork_types. + +Definition encode_transaction : M unit := + (* + Encode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + + +Definition decode_transaction : M unit := + (* + Decode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + 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..3e073bba06 --- /dev/null +++ b/coq/ethereum/berlin/trie.v @@ -0,0 +1,274 @@ +(* +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 : M unit := + (* + 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 *) + let* encoded := rlp.["encode"] (| + unencoded + |) in + (* TODO statement *) + + +Definition encode_node : M unit := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + + +Definition copy_trie : M unit := + (* + 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 *) + + +Definition trie_set : 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 *) + + +Definition trie_get : M unit := + (* + 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 *) + + +Definition common_prefix_length : M unit := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition nibble_list_to_compact : M unit := + (* + 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. + *) + let* compact := bytearray (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_nibble_list : M unit := + (* + 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. + *) + let* nibble_list := bytearray (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _prepare_trie : M unit := + (* + 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 *) + + +Definition root : M unit := + (* + 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. + *) + let* obj := _prepare_trie (| + trie, + get_storage_root + |) in + let* root_node := encode_internal_node (| + patricialize (| + obj, + Uint (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + + +Definition patricialize : M unit := + (* + 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 *) + let* arbitrary_key := next (| + iter (| + obj + |) + |) in + (* TODO statement *) + let* substring := (* TODO expression *) in + let* prefix_length := len (| + substring + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..beff4482b1 --- /dev/null +++ b/coq/ethereum/berlin/utils/__init__.v @@ -0,0 +1,4 @@ +(* +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..f90ce3c8d3 --- /dev/null +++ b/coq/ethereum/berlin/utils/address.v @@ -0,0 +1,99 @@ +(* +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 berlin.fork_types. + +Definition to_address : M unit := + (* + 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 *) + + +Definition compute_contract_address : M unit := + (* + 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. + *) + let* computed_address := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *) + |) + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition compute_create2_contract_address : M unit := + (* + 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. + *) + let* preimage := (* TODO expression *) in + let* computed_address := ethereum.crypto.hash.keccak256 (| + preimage + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + 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..93fb628067 --- /dev/null +++ b/coq/ethereum/berlin/utils/hexadecimal.v @@ -0,0 +1,68 @@ +(* +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 berlin.fork_types. + +Definition hex_to_root : M unit := + (* + 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 *) + + +Definition hex_to_bloom : M unit := + (* + 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 *) + + +Definition hex_to_address : M unit := + (* + 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 *) + 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..4e996471dc --- /dev/null +++ b/coq/ethereum/berlin/utils/message.v @@ -0,0 +1,82 @@ +(* +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 berlin.fork_types. +Require berlin.state. +Require berlin.vm. +Require berlin.vm.precompiled_contracts.mapping. +Require berlin.utils.address. + +Definition prepare_message : M unit := + (* + 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 *) + let* accessed_addresses := set (| + + |) in + do* accessed_addresses.["add"] (| + current_target + |) in + do* accessed_addresses.["add"] (| + caller + |) in + do* accessed_addresses.["update"] (| + vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS.["keys"] (| + + |) + |) in + do* accessed_addresses.["update"] (| + preaccessed_addresses + |) in + (* TODO statement *) + 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..77fe0bc4ab --- /dev/null +++ b/coq/ethereum/berlin/vm/__init__.v @@ -0,0 +1,69 @@ +(* +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 berlin.blocks. +Require berlin.fork_types. +Require berlin.state. +Require berlin.vm.precompiled_contracts. + +Definition incorporate_child_on_success : 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* evm.["accounts_to_delete"].["update"] (| + child_evm.["accounts_to_delete"] + |) in + do* evm.["touched_accounts"].["update"] (| + child_evm.["touched_accounts"] + |) in + (* TODO statement *) + do* evm.["accessed_addresses"].["update"] (| + child_evm.["accessed_addresses"] + |) in + do* evm.["accessed_storage_keys"].["update"] (| + child_evm.["accessed_storage_keys"] + |) in + + +Definition incorporate_child_on_error : 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 *) + (* TODO statement *) + 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..1784494410 --- /dev/null +++ b/coq/ethereum/berlin/vm/exceptions.v @@ -0,0 +1,15 @@ +(* +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..0d2e1de7e8 --- /dev/null +++ b/coq/ethereum/berlin/vm/gas.v @@ -0,0 +1,151 @@ +(* +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 berlin.vm.exceptions. + +Definition charge_gas : 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 (| + int (| + amount + |) + |) + |) in + (* TODO statement *) + + +Definition calculate_memory_gas_cost : M unit := + (* + 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. + *) + let* size_in_words := (* TODO expression *) in + let* linear_cost := (* TODO expression *) in + let* quadratic_cost := (* TODO expression *) in + let* total_gas_cost := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_gas_extend_memory : M unit := + (* + 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` + *) + let* size_to_extend := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* to_be_paid := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* current_size := ethereum_types.numeric.Uint (| + len (| + memory + |) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_message_call_gas : M unit := + (* + 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` + *) + let* call_stipend := (* TODO expression *) in + (* TODO statement *) + let* gas := min (| + gas, + max_message_call_gas (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + + +Definition max_message_call_gas : M unit := + (* + 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 *) + 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..b36b1ebfef --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/__init__.v @@ -0,0 +1,15 @@ +(* +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..eecb9665f5 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/arithmetic.v @@ -0,0 +1,387 @@ +(* +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 berlin.vm.gas. +Require berlin.vm.stack. + +Definition add : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_add"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition sub : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_sub"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mul : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + let* result := x.["wrapping_mul"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition div : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |) in + let* divisor := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + quotient + |) in + (* TODO statement *) + + +Definition sdiv : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* divisor := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + quotient + |) + |) in + (* TODO statement *) + + +Definition mod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + remainder + |) in + (* TODO statement *) + + +Definition smod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* y := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + remainder + |) + |) in + (* TODO statement *) + + +Definition addmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mulmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition exp : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* base := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent_bits := exponent.["bit_length"] (| + + |) in + let* exponent_bytes := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* result := ethereum_types.numeric.U256 (| + pow (| + base, + exponent, + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signextend : 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. + + *) + let* byte_num := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..2aaf2749ca --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/bitwise.v @@ -0,0 +1,245 @@ +(* +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 berlin.vm.gas. +Require berlin.vm.stack. + +Definition bitwise_and : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_or : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_xor : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_not : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition get_byte : 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. + + *) + let* byte_index := stack.pop (| + evm.["stack"] + |) in + let* word := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shl : 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. + *) + let* shift := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shr : 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. + *) + let* shift := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_sar : 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. + *) + let* shift := int (| + stack.pop (| + evm.["stack"] + |) + |) in + let* signed_value := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..b5be147a64 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/block.v @@ -0,0 +1,207 @@ +(* +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 berlin.vm.gas. +Require berlin.vm.stack. + +Definition block_hash : 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. + + *) + let* block_number := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOCK_HASH + |) in + let* max_block_number := (* TODO expression *) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + + +Definition coinbase : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["coinbase"] + |) + |) in + (* TODO statement *) + + +Definition timestamp : 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 (| + evm.["stack"], + evm.["env"].["time"] + |) in + (* TODO statement *) + + +Definition number : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["number"] + |) + |) in + (* TODO statement *) + + +Definition difficulty : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["difficulty"] + |) + |) in + (* TODO statement *) + + +Definition gas_limit : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_limit"] + |) + |) in + (* TODO statement *) + + +Definition chain_id : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["chain_id"] + |) + |) in + (* TODO statement *) + 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..a74bce325e --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/comparison.v @@ -0,0 +1,206 @@ +(* +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 berlin.vm.gas. +Require berlin.vm.stack. + +Definition less_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_less_than : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition greater_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_greater_than : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition equal : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition is_zero : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..cf98b07c7b --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/control_flow.v @@ -0,0 +1,156 @@ +(* +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 berlin.vm.gas. +Require berlin.vm.exceptions. +Require berlin.vm.stack. + +Definition stop : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition jump : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_MID + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition jumpi : 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. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* conditional_value := stack.pop (| + evm.["stack"] + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_HIGH + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition pc : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["pc"] + |) + |) in + (* TODO statement *) + + +Definition gas_left : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + + +Definition jumpdest : 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 *) + (* TODO statement *) + 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..2e255b4efd --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/environment.v @@ -0,0 +1,544 @@ +(* +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 berlin.fork_types. +Require berlin.state. +Require berlin.utils.address. +Require berlin.vm.memory. +Require berlin.vm.exceptions. +Require berlin.vm.gas. +Require berlin.vm.stack. + +Definition address : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["current_target"] + |) + |) in + (* TODO statement *) + + +Definition balance : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* balance := state.get_account (| + evm.["env"].["state"], + address + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition origin : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["origin"] + |) + |) in + (* TODO statement *) + + +Definition caller : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["caller"] + |) + |) in + (* TODO statement *) + + +Definition callvalue : 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 (| + evm.["stack"], + evm.["message"].["value"] + |) in + (* TODO statement *) + + +Definition calldataload : 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. + + *) + let* start_index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + start_index, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + value + |) + |) in + (* TODO statement *) + + +Definition calldatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["message"].["data"] + |) + |) + |) in + (* TODO statement *) + + +Definition calldatacopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* data_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + data_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition codesize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["code"] + |) + |) + |) in + (* TODO statement *) + + +Definition codecopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["code"], + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition gasprice : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_price"] + |) + |) in + (* TODO statement *) + + +Definition extcodesize : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* codesize := ethereum_types.numeric.U256 (| + len (| + state.get_account (| + evm.["env"].["state"], + address + |).["code"] + |) + |) in + do* stack.push (| + evm.["stack"], + codesize + |) in + (* TODO statement *) + + +Definition extcodecopy : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* code := state.get_account (| + evm.["env"].["state"], + address + |).["code"] in + let* value := vm.memory.buffer_read (| + code, + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition returndatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["return_data"] + |) + |) + |) in + (* TODO statement *) + + +Definition returndatacopy : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* return_data_start_position := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition extcodehash : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* account := state.get_account (| + evm.["env"].["state"], + address + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + codehash + |) in + (* TODO statement *) + + +Definition self_balance : 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 + let* balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + 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..aeef55db2c --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/keccak.v @@ -0,0 +1,67 @@ +(* +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 berlin.vm.gas. +Require berlin.vm.memory. +Require berlin.vm.stack. + +Definition keccak : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* word_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + let* hash := ethereum.crypto.hash.keccak256 (| + data + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + 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..8183fbf41c --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/log.v @@ -0,0 +1,61 @@ +(* +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 berlin.blocks. +Require berlin.vm.exceptions. +Require berlin.vm.gas. +Require berlin.vm.memory. +Require berlin.vm.stack. + +Definition log_n : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* topics := (* TODO expression *) in + (* TODO statement *) + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* log_entry := blocks.Log (| + + |) in + (* TODO assignment *) + (* TODO statement *) + 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..1af3aa3a10 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/memory.v @@ -0,0 +1,158 @@ +(* +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 berlin.vm.gas. +Require berlin.vm.memory. +Require berlin.vm.stack. + +Definition mstore : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* memory.memory_write (| + evm.["memory"], + start_position, + value + |) in + (* TODO statement *) + + +Definition mstore8 : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + (* TODO expression *) + |) in + do* memory.memory_write (| + evm.["memory"], + start_position, + normalized_bytes_value + |) in + (* TODO statement *) + + +Definition mload : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.memory_read_bytes (| + evm.["memory"], + start_position, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition msize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["memory"] + |) + |) + |) in + (* TODO statement *) + 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..8b1ac68678 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/stack.v @@ -0,0 +1,133 @@ +(* +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 berlin.vm.exceptions. +Require berlin.vm.gas. +Require berlin.vm.memory. + +Definition pop : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* stack.["pop"] (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BASE + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition push_n : 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 + let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + evm.["code"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + num_bytes + |) + |) + |) in + do* stack.["push"] (| + evm.["stack"], + data_to_push + |) in + (* TODO statement *) + + +Definition dup_n : 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 *) + let* data_to_duplicate := (* TODO expression *) in + do* stack.["push"] (| + evm.["stack"], + data_to_duplicate + |) in + (* TODO statement *) + + +Definition swap_n : 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 *) + (* TODO statement *) + 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..cea8a2837c --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/storage.v @@ -0,0 +1,97 @@ +(* +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 berlin.state. +Require berlin.vm.exceptions. +Require berlin.vm.gas. +Require berlin.vm.stack. + +Definition sload : 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. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + (* TODO statement *) + let* value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition sstore : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + (* TODO statement *) + let* original_value := state.get_storage_original (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + let* current_value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + let* gas_cost := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + do* state.set_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + 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..5b11f67828 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/system.v @@ -0,0 +1,589 @@ +(* +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 berlin.fork_types. +Require berlin.state. +Require berlin.utils.address. +Require berlin.vm.exceptions. +Require berlin.vm.gas. +Require berlin.vm.memory. +Require berlin.vm.stack. + +Definition generic_create : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + do* evm.["accessed_addresses"].["add"] (| + contract_address + |) in + let* create_message_gas := gas.max_message_call_gas (| + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + let* sender_address := evm.["message"].["current_target"] in + let* sender := state.get_account (| + evm.["env"].["state"], + sender_address + |) in + (* TODO statement *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) in + do* state.increment_nonce (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |) in + let* child_message := Message (| + + |) in + let* child_evm := process_create_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + + +Definition create : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_contract_address (| + evm.["message"].["current_target"], + state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["nonce"] + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size + |) in + (* TODO statement *) + + +Definition create2 : 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. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* salt := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* call_data_words := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_create2_contract_address (| + evm.["message"].["current_target"], + salt, + memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size + |) in + (* TODO statement *) + + +Definition return_ : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + + +Definition generic_call : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_input_start_position, + memory_input_size + |) in + let* code := state.get_account (| + evm.["env"].["state"], + code_address + |).["code"] in + let* child_message := Message (| + + |) in + let* child_evm := process_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + let* actual_output_size := min (| + memory_output_size, + ethereum_types.numeric.U256 (| + len (| + child_evm.["output"] + |) + |) + |) in + do* memory.memory_write (| + evm.["memory"], + memory_output_start_position, + (* TODO expression *) + |) in + + +Definition call : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* create_gas_cost := (* TODO expression *) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition callcode : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* to := evm.["message"].["current_target"] in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition selfdestruct : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* beneficiary := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* gas_cost := gas.GAS_SELF_DESTRUCT in + (* TODO statement *) + (* TODO statement *) + let* originator := evm.["message"].["current_target"] in + let* refunded_accounts := evm.["accounts_to_delete"] in + let* parent_evm := evm.["message"].["parent_evm"] in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + let* beneficiary_balance := state.get_account (| + evm.["env"].["state"], + beneficiary + |).["balance"] in + let* originator_balance := state.get_account (| + evm.["env"].["state"], + originator + |).["balance"] in + do* state.set_account_balance (| + evm.["env"].["state"], + beneficiary, + (* TODO expression *) + |) in + do* state.set_account_balance (| + evm.["env"].["state"], + originator, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* evm.["accounts_to_delete"].["add"] (| + originator + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition delegatecall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + access_gas_cost + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + evm.["message"].["value"], + evm.["message"].["caller"], + evm.["message"].["current_target"], + code_address, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition staticcall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + access_gas_cost + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + evm.["message"].["current_target"], + to, + to, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition revert : 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. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + extend_memory.["cost"] + |) in + (* TODO statement *) + let* output := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + 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..19315318ab --- /dev/null +++ b/coq/ethereum/berlin/vm/interpreter.v @@ -0,0 +1,159 @@ +(* +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 berlin.blocks. +Require berlin.fork_types. +Require berlin.state. +Require berlin.vm. +Require berlin.vm.gas. +Require berlin.vm.precompiled_contracts.mapping. +Require berlin.vm.exceptions. +Require berlin.vm.instructions. +Require berlin.vm.runtime. + +Definition process_message_call : M unit := + (* + 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 *) + let* tx_end := ethereum.trace.TransactionEnd (| + (* TODO expression *), + evm.["output"], + evm.["error"] + |) in + do* ethereum.trace.evm_trace (| + evm, + tx_end + |) in + (* TODO statement *) + + +Definition process_create_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.destroy_storage (| + env.["state"], + message.["current_target"] + |) in + do* state.mark_account_created (| + env.["state"], + message.["current_target"] + |) in + do* state.increment_nonce (| + env.["state"], + message.["current_target"] + |) in + let* evm := process_message (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.touch_account (| + env.["state"], + message.["current_target"] + |) in + (* TODO statement *) + let* evm := execute_code (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition execute_code : M unit := + (* + 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 + *) + let* code := message.["code"] in + let* valid_jump_destinations := runtime.get_valid_jump_destinations (| + code + |) in + let* evm := Evm (| + + |) in + (* TODO statement *) + (* TODO statement *) + 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..94b6a44639 --- /dev/null +++ b/coq/ethereum/berlin/vm/memory.v @@ -0,0 +1,75 @@ +(* +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 : 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 *) + + +Definition memory_read_bytes : M unit := + (* + 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 *) + + +Definition buffer_read : M unit := + (* + 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 *) + 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..c6802d7c7e --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/__init__.v @@ -0,0 +1,16 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require 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..b1a1019a08 --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,187 @@ +(* +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 berlin.vm. +Require berlin.vm.gas. +Require berlin.vm.memory. +Require berlin.vm.exceptions. + +Definition alt_bn128_add : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* x1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x1_bytes + |) + |) in + let* y1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y1_bytes + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := (* TODO expression *) in + (* TODO assignment *) + + +Definition alt_bn128_mul : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* n := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := p0.["mul_by"] (| + n + |) in + (* TODO assignment *) + + +Definition alt_bn128_pairing_check : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..a50ae00501 --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,41 @@ +(* +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 berlin.vm. +Require berlin.vm.gas. +Require berlin.vm.exceptions. + +Definition blake2f : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + (* TODO statement *) + let* blake2b := ethereum.crypto.blake2.Blake2b (| + + |) in + (* TODO assignment *) + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + 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..587da7fc61 --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,93 @@ +(* +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 berlin.vm. +Require berlin.vm.gas. +Require berlin.vm.memory. + +Definition ecrecover : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_ECRECOVER + |) in + let* message_hash_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* message_hash := ethereum.crypto.hash.Hash32 (| + message_hash_bytes + |) in + let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + address, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..108e609b22 --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/identity.v @@ -0,0 +1,36 @@ +(* +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 berlin.vm. +Require berlin.vm.gas. + +Definition identity : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..e1a6f7a35e --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/mapping.v @@ -0,0 +1,23 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require berlin.fork_types. +Require berlin.vm.precompiled_contracts.alt_bn128. +Require berlin.vm.precompiled_contracts.blake2f. +Require berlin.vm.precompiled_contracts.ecrecover. +Require berlin.vm.precompiled_contracts.identity. +Require berlin.vm.precompiled_contracts.modexp. +Require berlin.vm.precompiled_contracts.ripemd160. +Require 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..a3d758ba3a --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/modexp.v @@ -0,0 +1,203 @@ +(* +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 berlin.vm. +Require berlin.vm.gas. +Require berlin.vm.memory. + +Definition modexp : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + let* data := evm.["message"].["data"] in + let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_start := (* TODO expression *) in + let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + min (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + exp_length + |) + |) + |) in + do* vm.gas.charge_gas (| + evm, + gas_cost (| + base_length, + modulus_length, + exp_length, + exp_head + |) + |) in + (* TODO statement *) + let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + base_length + |) + |) in + let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + exp_length + |) + |) in + let* modulus_start := (* TODO expression *) in + let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + modulus_start, + modulus_length + |) + |) in + (* TODO statement *) + + +Definition complexity : M unit := + (* + 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. + *) + let* max_length := max (| + ethereum_types.numeric.Uint (| + base_length + |), + ethereum_types.numeric.Uint (| + modulus_length + |) + |) in + let* words := (* TODO expression *) in + (* TODO statement *) + + +Definition iterations : M unit := + (* + 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 *) + + +Definition gas_cost : M unit := + (* + 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. + *) + let* multiplication_complexity := complexity (| + base_length, + modulus_length + |) in + let* iteration_count := iterations (| + exponent_length, + exponent_head + |) in + let* cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..bc5e73dd3c --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,42 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + let* hash_bytes := hashlib.["new"] (| + (* TODO expression *), + data + |).["digest"] (| + + |) in + let* padded_hash := left_pad_zero_bytes (| + hash_bytes, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..da6972d411 --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/sha256.v @@ -0,0 +1,32 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..818241a214 --- /dev/null +++ b/coq/ethereum/berlin/vm/runtime.v @@ -0,0 +1,49 @@ +(* +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 berlin.vm.instructions. + +Definition get_valid_jump_destinations : M unit := + (* + 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. + *) + let* valid_jump_destinations := set (| + + |) in + let* pc := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..27ef379dba --- /dev/null +++ b/coq/ethereum/berlin/vm/stack.v @@ -0,0 +1,53 @@ +(* +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 berlin.vm.exceptions. + +Definition pop : M unit := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + + +Definition push : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + 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..14ce5a10a1 --- /dev/null +++ b/coq/ethereum/byzantium/__init__.v @@ -0,0 +1,7 @@ +(* +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..6c9a220f34 --- /dev/null +++ b/coq/ethereum/byzantium/blocks.v @@ -0,0 +1,19 @@ +(* +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 ..crypto.hash. +Require byzantium.fork_types. +Require 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..09494c0e11 --- /dev/null +++ b/coq/ethereum/byzantium/bloom.v @@ -0,0 +1,66 @@ +(* +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 byzantium.blocks. +Require byzantium.fork_types. + +Definition add_to_bloom : 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. + *) + let* hash := ethereum.crypto.hash.keccak256 (| + bloom_entry + |) in + (* TODO statement *) + + +Definition logs_bloom : M unit := + (* + 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 *) + 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..ac9ee32443 --- /dev/null +++ b/coq/ethereum/byzantium/fork.v @@ -0,0 +1,760 @@ +(* +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 byzantium.blocks. +Require byzantium.bloom. +Require byzantium.fork_types. +Require byzantium.state. +Require byzantium.transactions. +Require byzantium.trie. +Require byzantium.utils.message. +Require byzantium.vm.interpreter. + +Definition apply_fork : M unit := + (* + 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 *) + + +Definition get_last_256_block_hashes : M unit := + (* + 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. + *) + let* recent_blocks := (* TODO expression *) in + (* TODO statement *) + let* recent_block_hashes := (* TODO expression *) in + (* TODO statement *) + let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *).["header"] + |) + |) in + do* recent_block_hashes.["append"] (| + most_recent_block_hash + |) in + (* TODO statement *) + + +Definition state_transition : 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`. + *) + let* parent_header := (* TODO expression *).["header"] in + do* validate_header (| + block.["header"], + parent_header + |) in + do* validate_ommers (| + block.["ommers"], + block.["header"], + chain + |) in + let* apply_body_output := apply_body (| + chain.["state"], + get_last_256_block_hashes (| + chain + |), + block.["header"].["coinbase"], + block.["header"].["number"], + block.["header"].["gas_limit"], + block.["header"].["timestamp"], + block.["header"].["difficulty"], + block.["transactions"], + block.["ommers"], + chain.["chain_id"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* chain.["blocks"].["append"] (| + block + |) in + (* TODO statement *) + + +Definition validate_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 + *) + let* parent_has_ommers := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* block_difficulty := calculate_block_difficulty (| + header.["number"], + header.["timestamp"], + parent_header.["timestamp"], + parent_header.["difficulty"], + parent_has_ommers + |) in + (* TODO statement *) + let* block_parent_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + parent_header + |) + |) in + (* TODO statement *) + do* validate_proof_of_work (| + header + |) in + + +Definition generate_header_hash_for_pow : M unit := + (* + 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. + *) + let* header_data_without_pow_artefacts := (* TODO expression *) in + (* TODO statement *) + + +Definition validate_proof_of_work : 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. + *) + let* header_hash := generate_header_hash_for_pow (| + header + |) in + let* cache := ethereum.ethash.generate_cache (| + header.["number"] + |) in + (* TODO assignment *) + (* TODO statement *) + let* limit := (* TODO expression *) in + (* TODO statement *) + + +Definition check_transaction : M unit := + (* + 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 *) + let* sender_address := recover_sender (| + chain_id, + tx + |) in + (* TODO statement *) + + +Definition make_receipt : M unit := + (* + 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. + *) + let* receipt := blocks.Receipt (| + + |) in + (* TODO statement *) + + +Definition apply_body : M unit := + (* + 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. + *) + let* gas_available := block_gas_limit in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* pay_rewards (| + state, + block_number, + coinbase, + ommers + |) in + let* block_gas_used := (* TODO expression *) in + let* block_logs_bloom := bloom.logs_bloom (| + block_logs + |) in + (* TODO statement *) + + +Definition validate_ommers : 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. + *) + let* block_hash := rlp.["rlp_hash"] (| + block_header + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* ommers_hashes := (* TODO expression *) in + (* TODO statement *) + let* recent_canonical_blocks := (* TODO expression *) in + let* recent_canonical_block_hashes := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition pay_rewards : 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. + *) + let* ommer_count := ethereum_types.numeric.U256 (| + len (| + ommers + |) + |) in + let* miner_reward := (* TODO expression *) in + do* state.create_ether (| + state, + coinbase, + miner_reward + |) in + (* TODO statement *) + + +Definition process_transaction : M unit := + (* + 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 *) + let* sender := env.["origin"] in + let* sender_account := state.get_account (| + env.["state"], + sender + |) in + let* gas_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* gas := (* TODO expression *) in + do* state.increment_nonce (| + env.["state"], + sender + |) in + let* sender_balance_after_gas_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + ethereum_types.numeric.U256 (| + sender_balance_after_gas_fee + |) + |) in + let* message := utils.message.prepare_message (| + sender, + tx.["to"], + tx.["value"], + tx.["data"], + gas, + env + |) in + let* output := vm.interpreter.process_message_call (| + message, + env + |) in + let* gas_used := (* TODO expression *) in + let* gas_refund := min (| + (* TODO expression *), + ethereum_types.numeric.Uint (| + output.["refund_counter"] + |) + |) in + let* gas_refund_amount := (* TODO expression *) in + let* transaction_fee := (* TODO expression *) in + let* total_gas_used := (* TODO expression *) in + let* sender_balance_after_refund := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + sender_balance_after_refund + |) in + let* coinbase_balance_after_mining_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_transaction : M unit := + (* + 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 *) + + +Definition calculate_intrinsic_cost : M unit := + (* + 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. + *) + let* data_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition recover_sender : M unit := + (* + 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 *) + + +Definition signing_hash_pre155 : M unit := + (* + 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 *) + + +Definition signing_hash_155 : M unit := + (* + 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 *) + + +Definition compute_header_hash : M unit := + (* + 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 *) + + +Definition check_gas_limit : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_block_difficulty : M unit := + (* + 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. + *) + let* offset := (* TODO expression *) in + let* difficulty := (* TODO expression *) in + let* num_bomb_periods := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..14de99d5e5 --- /dev/null +++ b/coq/ethereum/byzantium/fork_types.v @@ -0,0 +1,29 @@ +(* +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 ..crypto.hash. + +Definition encode_account : M unit := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + 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..e96991d31a --- /dev/null +++ b/coq/ethereum/byzantium/state.v @@ -0,0 +1,543 @@ +(* +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 byzantium.fork_types. +Require byzantium.trie. + +Definition close_state : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition begin_transaction : 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* state.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + + +Definition commit_transaction : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* state.["_snapshots"].["pop"] (| + + |) in + + +Definition rollback_transaction : 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 *) + + +Definition get_account : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition get_account_optional : M unit := + (* + 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. + *) + let* account := trie.trie_get (| + state.["_main_trie"], + address + |) in + (* TODO statement *) + + +Definition set_account : 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 (| + state.["_main_trie"], + address, + account + |) in + + +Definition destroy_account : 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* destroy_storage (| + state, + address + |) in + do* set_account (| + state, + address, + (* TODO expression *) + |) in + + +Definition destroy_storage : 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 *) + + +Definition get_storage : M unit := + (* + 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. + *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_storage : 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 *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition storage_root : M unit := + (* + 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 *) + + +Definition state_root : M unit := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition account_exists : M unit := + (* + 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 *) + + +Definition account_has_code_or_nonce : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_empty : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition account_exists_and_is_empty : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_alive : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition modify_state : M unit := + (* + Modify an `Account` in the `State`. + *) + do* set_account (| + state, + address, + ethereum_types.frozen.modify (| + get_account (| + state, + address + |), + f + |) + |) in + + +Definition move_ether : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* modify_state (| + state, + sender_address, + reduce_sender_balance + |) in + do* modify_state (| + state, + recipient_address, + increase_recipient_balance + |) in + + +Definition set_account_balance : 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* modify_state (| + state, + address, + set_balance + |) in + + +Definition touch_account : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + + +Definition increment_nonce : 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* modify_state (| + state, + address, + increase_nonce + |) in + + +Definition set_code : 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* modify_state (| + state, + address, + write_code + |) in + + +Definition create_ether : 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* modify_state (| + state, + address, + increase_balance + |) in + 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/translation/transactions.v b/coq/ethereum/byzantium/transactions.v similarity index 89% rename from coq/translation/transactions.v rename to coq/ethereum/byzantium/transactions.v index 79554e3955..37fb6cb470 100644 --- a/coq/translation/transactions.v +++ b/coq/ethereum/byzantium/transactions.v @@ -9,5 +9,4 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require exceptions. -Require fork_types. +Require 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..548de91e1c --- /dev/null +++ b/coq/ethereum/byzantium/trie.v @@ -0,0 +1,274 @@ +(* +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 : M unit := + (* + 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 *) + let* encoded := rlp.["encode"] (| + unencoded + |) in + (* TODO statement *) + + +Definition encode_node : M unit := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + + +Definition copy_trie : M unit := + (* + 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 *) + + +Definition trie_set : 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 *) + + +Definition trie_get : M unit := + (* + 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 *) + + +Definition common_prefix_length : M unit := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition nibble_list_to_compact : M unit := + (* + 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. + *) + let* compact := bytearray (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_nibble_list : M unit := + (* + 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. + *) + let* nibble_list := bytearray (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _prepare_trie : M unit := + (* + 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 *) + + +Definition root : M unit := + (* + 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. + *) + let* obj := _prepare_trie (| + trie, + get_storage_root + |) in + let* root_node := encode_internal_node (| + patricialize (| + obj, + Uint (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + + +Definition patricialize : M unit := + (* + 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 *) + let* arbitrary_key := next (| + iter (| + obj + |) + |) in + (* TODO statement *) + let* substring := (* TODO expression *) in + let* prefix_length := len (| + substring + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..beff4482b1 --- /dev/null +++ b/coq/ethereum/byzantium/utils/__init__.v @@ -0,0 +1,4 @@ +(* +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..4ed0274673 --- /dev/null +++ b/coq/ethereum/byzantium/utils/address.v @@ -0,0 +1,67 @@ +(* +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 byzantium.fork_types. + +Definition to_address : M unit := + (* + 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 *) + + +Definition compute_contract_address : M unit := + (* + 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. + *) + let* computed_address := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *) + |) + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + 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..3741d1ddf7 --- /dev/null +++ b/coq/ethereum/byzantium/utils/hexadecimal.v @@ -0,0 +1,68 @@ +(* +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 byzantium.fork_types. + +Definition hex_to_root : M unit := + (* + 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 *) + + +Definition hex_to_bloom : M unit := + (* + 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 *) + + +Definition hex_to_address : M unit := + (* + 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 *) + 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..5e07003262 --- /dev/null +++ b/coq/ethereum/byzantium/utils/message.v @@ -0,0 +1,59 @@ +(* +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 byzantium.fork_types. +Require byzantium.state. +Require byzantium.vm. +Require byzantium.utils.address. + +Definition prepare_message : M unit := + (* + 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 *) + 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..5ce592e183 --- /dev/null +++ b/coq/ethereum/byzantium/vm/__init__.v @@ -0,0 +1,63 @@ +(* +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 byzantium.blocks. +Require byzantium.fork_types. +Require byzantium.state. +Require byzantium.vm.precompiled_contracts. + +Definition incorporate_child_on_success : 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* evm.["accounts_to_delete"].["update"] (| + child_evm.["accounts_to_delete"] + |) in + do* evm.["touched_accounts"].["update"] (| + child_evm.["touched_accounts"] + |) in + (* TODO statement *) + + +Definition incorporate_child_on_error : 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 *) + (* TODO statement *) + 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..1784494410 --- /dev/null +++ b/coq/ethereum/byzantium/vm/exceptions.v @@ -0,0 +1,15 @@ +(* +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..75ae562094 --- /dev/null +++ b/coq/ethereum/byzantium/vm/gas.v @@ -0,0 +1,151 @@ +(* +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 byzantium.vm.exceptions. + +Definition charge_gas : 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 (| + int (| + amount + |) + |) + |) in + (* TODO statement *) + + +Definition calculate_memory_gas_cost : M unit := + (* + 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. + *) + let* size_in_words := (* TODO expression *) in + let* linear_cost := (* TODO expression *) in + let* quadratic_cost := (* TODO expression *) in + let* total_gas_cost := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_gas_extend_memory : M unit := + (* + 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` + *) + let* size_to_extend := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* to_be_paid := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* current_size := ethereum_types.numeric.Uint (| + len (| + memory + |) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_message_call_gas : M unit := + (* + 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` + *) + let* call_stipend := (* TODO expression *) in + (* TODO statement *) + let* gas := min (| + gas, + max_message_call_gas (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + + +Definition max_message_call_gas : M unit := + (* + 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 *) + 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..b36b1ebfef --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/__init__.v @@ -0,0 +1,15 @@ +(* +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..14f853a54b --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/arithmetic.v @@ -0,0 +1,387 @@ +(* +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 byzantium.vm.gas. +Require byzantium.vm.stack. + +Definition add : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_add"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition sub : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_sub"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mul : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + let* result := x.["wrapping_mul"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition div : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |) in + let* divisor := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + quotient + |) in + (* TODO statement *) + + +Definition sdiv : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* divisor := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + quotient + |) + |) in + (* TODO statement *) + + +Definition mod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + remainder + |) in + (* TODO statement *) + + +Definition smod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* y := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + remainder + |) + |) in + (* TODO statement *) + + +Definition addmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mulmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition exp : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* base := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent_bits := exponent.["bit_length"] (| + + |) in + let* exponent_bytes := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* result := ethereum_types.numeric.U256 (| + pow (| + base, + exponent, + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signextend : 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. + + *) + let* byte_num := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..7b2cee4bce --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/bitwise.v @@ -0,0 +1,156 @@ +(* +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 byzantium.vm.gas. +Require byzantium.vm.stack. + +Definition bitwise_and : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_or : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_xor : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_not : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition get_byte : 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. + + *) + let* byte_index := stack.pop (| + evm.["stack"] + |) in + let* word := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..e5341af50b --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/block.v @@ -0,0 +1,183 @@ +(* +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 byzantium.vm.gas. +Require byzantium.vm.stack. + +Definition block_hash : 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. + + *) + let* block_number := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOCK_HASH + |) in + let* max_block_number := (* TODO expression *) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + + +Definition coinbase : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["coinbase"] + |) + |) in + (* TODO statement *) + + +Definition timestamp : 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 (| + evm.["stack"], + evm.["env"].["time"] + |) in + (* TODO statement *) + + +Definition number : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["number"] + |) + |) in + (* TODO statement *) + + +Definition difficulty : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["difficulty"] + |) + |) in + (* TODO statement *) + + +Definition gas_limit : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_limit"] + |) + |) in + (* TODO statement *) + 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..51d912e7b5 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/comparison.v @@ -0,0 +1,206 @@ +(* +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 byzantium.vm.gas. +Require byzantium.vm.stack. + +Definition less_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_less_than : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition greater_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_greater_than : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition equal : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition is_zero : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..83f597f9a9 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/control_flow.v @@ -0,0 +1,156 @@ +(* +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 byzantium.vm.gas. +Require byzantium.vm.exceptions. +Require byzantium.vm.stack. + +Definition stop : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition jump : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_MID + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition jumpi : 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. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* conditional_value := stack.pop (| + evm.["stack"] + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_HIGH + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition pc : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["pc"] + |) + |) in + (* TODO statement *) + + +Definition gas_left : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + + +Definition jumpdest : 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 *) + (* TODO statement *) + 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..86d17235a8 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/environment.v @@ -0,0 +1,499 @@ +(* +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 byzantium.state. +Require byzantium.utils.address. +Require byzantium.vm.memory. +Require byzantium.vm.exceptions. +Require byzantium.vm.gas. +Require byzantium.vm.stack. + +Definition address : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["current_target"] + |) + |) in + (* TODO statement *) + + +Definition balance : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BALANCE + |) in + let* balance := state.get_account (| + evm.["env"].["state"], + address + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition origin : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["origin"] + |) + |) in + (* TODO statement *) + + +Definition caller : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["caller"] + |) + |) in + (* TODO statement *) + + +Definition callvalue : 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 (| + evm.["stack"], + evm.["message"].["value"] + |) in + (* TODO statement *) + + +Definition calldataload : 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. + + *) + let* start_index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + start_index, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + value + |) + |) in + (* TODO statement *) + + +Definition calldatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["message"].["data"] + |) + |) + |) in + (* TODO statement *) + + +Definition calldatacopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* data_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + data_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition codesize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["code"] + |) + |) + |) in + (* TODO statement *) + + +Definition codecopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["code"], + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition gasprice : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_price"] + |) + |) in + (* TODO statement *) + + +Definition extcodesize : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_EXTERNAL + |) in + let* codesize := ethereum_types.numeric.U256 (| + len (| + state.get_account (| + evm.["env"].["state"], + address + |).["code"] + |) + |) in + do* stack.push (| + evm.["stack"], + codesize + |) in + (* TODO statement *) + + +Definition extcodecopy : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* code := state.get_account (| + evm.["env"].["state"], + address + |).["code"] in + let* value := vm.memory.buffer_read (| + code, + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition returndatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["return_data"] + |) + |) + |) in + (* TODO statement *) + + +Definition returndatacopy : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* return_data_start_position := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + 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..aad67596bc --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/keccak.v @@ -0,0 +1,67 @@ +(* +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 byzantium.vm.gas. +Require byzantium.vm.memory. +Require byzantium.vm.stack. + +Definition keccak : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* word_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + let* hash := ethereum.crypto.hash.keccak256 (| + data + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + 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..9da3e01eaa --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/log.v @@ -0,0 +1,61 @@ +(* +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 byzantium.blocks. +Require byzantium.vm.exceptions. +Require byzantium.vm.gas. +Require byzantium.vm.memory. +Require byzantium.vm.stack. + +Definition log_n : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* topics := (* TODO expression *) in + (* TODO statement *) + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* log_entry := blocks.Log (| + + |) in + (* TODO assignment *) + (* TODO statement *) + 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..c14815403a --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/memory.v @@ -0,0 +1,158 @@ +(* +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 byzantium.vm.gas. +Require byzantium.vm.memory. +Require byzantium.vm.stack. + +Definition mstore : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* memory.memory_write (| + evm.["memory"], + start_position, + value + |) in + (* TODO statement *) + + +Definition mstore8 : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + (* TODO expression *) + |) in + do* memory.memory_write (| + evm.["memory"], + start_position, + normalized_bytes_value + |) in + (* TODO statement *) + + +Definition mload : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.memory_read_bytes (| + evm.["memory"], + start_position, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition msize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["memory"] + |) + |) + |) in + (* TODO statement *) + 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..38bb843610 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/stack.v @@ -0,0 +1,133 @@ +(* +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 byzantium.vm.exceptions. +Require byzantium.vm.gas. +Require byzantium.vm.memory. + +Definition pop : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* stack.["pop"] (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BASE + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition push_n : 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 + let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + evm.["code"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + num_bytes + |) + |) + |) in + do* stack.["push"] (| + evm.["stack"], + data_to_push + |) in + (* TODO statement *) + + +Definition dup_n : 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 *) + let* data_to_duplicate := (* TODO expression *) in + do* stack.["push"] (| + evm.["stack"], + data_to_duplicate + |) in + (* TODO statement *) + + +Definition swap_n : 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 *) + (* TODO statement *) + 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..0ad464fe24 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/storage.v @@ -0,0 +1,90 @@ +(* +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 byzantium.state. +Require byzantium.vm.exceptions. +Require byzantium.vm.gas. +Require byzantium.vm.stack. + +Definition sload : 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. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_SLOAD + |) in + let* value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition sstore : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + let* current_value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + do* state.set_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + 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..26d4c0fbb3 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/system.v @@ -0,0 +1,494 @@ +(* +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 byzantium.fork_types. +Require byzantium.state. +Require byzantium.utils.address. +Require byzantium.vm.exceptions. +Require byzantium.vm.gas. +Require byzantium.vm.memory. +Require byzantium.vm.stack. + +Definition create : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* create_message_gas := gas.max_message_call_gas (| + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + let* sender_address := evm.["message"].["current_target"] in + let* sender := state.get_account (| + evm.["env"].["state"], + sender_address + |) in + let* contract_address := utils.address.compute_contract_address (| + evm.["message"].["current_target"], + state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["nonce"] + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition return_ : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + + +Definition generic_call : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_input_start_position, + memory_input_size + |) in + let* code := state.get_account (| + evm.["env"].["state"], + code_address + |).["code"] in + let* child_message := Message (| + + |) in + let* child_evm := process_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + let* actual_output_size := min (| + memory_output_size, + ethereum_types.numeric.U256 (| + len (| + child_evm.["output"] + |) + |) + |) in + do* memory.memory_write (| + evm.["memory"], + memory_output_start_position, + (* TODO expression *) + |) in + + +Definition call : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* create_gas_cost := (* TODO expression *) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition callcode : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* to := evm.["message"].["current_target"] in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition selfdestruct : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* beneficiary := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* gas_cost := gas.GAS_SELF_DESTRUCT in + (* TODO statement *) + let* originator := evm.["message"].["current_target"] in + let* refunded_accounts := evm.["accounts_to_delete"] in + let* parent_evm := evm.["message"].["parent_evm"] in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + let* beneficiary_balance := state.get_account (| + evm.["env"].["state"], + beneficiary + |).["balance"] in + let* originator_balance := state.get_account (| + evm.["env"].["state"], + originator + |).["balance"] in + do* state.set_account_balance (| + evm.["env"].["state"], + beneficiary, + (* TODO expression *) + |) in + do* state.set_account_balance (| + evm.["env"].["state"], + originator, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* evm.["accounts_to_delete"].["add"] (| + originator + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition delegatecall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + gas.GAS_CALL + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + evm.["message"].["value"], + evm.["message"].["caller"], + evm.["message"].["current_target"], + code_address, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition staticcall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + gas.GAS_CALL + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + evm.["message"].["current_target"], + to, + to, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition revert : 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. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + extend_memory.["cost"] + |) in + (* TODO statement *) + let* output := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + 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..498c7ea8cf --- /dev/null +++ b/coq/ethereum/byzantium/vm/interpreter.v @@ -0,0 +1,155 @@ +(* +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 byzantium.blocks. +Require byzantium.fork_types. +Require byzantium.state. +Require byzantium.vm. +Require byzantium.vm.gas. +Require byzantium.vm.precompiled_contracts.mapping. +Require byzantium.vm.exceptions. +Require byzantium.vm.instructions. +Require byzantium.vm.runtime. + +Definition process_message_call : M unit := + (* + 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 *) + let* tx_end := ethereum.trace.TransactionEnd (| + (* TODO expression *), + evm.["output"], + evm.["error"] + |) in + do* ethereum.trace.evm_trace (| + evm, + tx_end + |) in + (* TODO statement *) + + +Definition process_create_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.destroy_storage (| + env.["state"], + message.["current_target"] + |) in + do* state.increment_nonce (| + env.["state"], + message.["current_target"] + |) in + let* evm := process_message (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.touch_account (| + env.["state"], + message.["current_target"] + |) in + (* TODO statement *) + let* evm := execute_code (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition execute_code : M unit := + (* + 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 + *) + let* code := message.["code"] in + let* valid_jump_destinations := runtime.get_valid_jump_destinations (| + code + |) in + let* evm := Evm (| + + |) in + (* TODO statement *) + (* TODO statement *) + 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..94b6a44639 --- /dev/null +++ b/coq/ethereum/byzantium/vm/memory.v @@ -0,0 +1,75 @@ +(* +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 : 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 *) + + +Definition memory_read_bytes : M unit := + (* + 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 *) + + +Definition buffer_read : M unit := + (* + 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 *) + 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..5820dc04d9 --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/__init__.v @@ -0,0 +1,16 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require 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..632bc984ba --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,187 @@ +(* +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 byzantium.vm. +Require byzantium.vm.gas. +Require byzantium.vm.memory. +Require byzantium.vm.exceptions. + +Definition alt_bn128_add : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* x1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x1_bytes + |) + |) in + let* y1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y1_bytes + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := (* TODO expression *) in + (* TODO assignment *) + + +Definition alt_bn128_mul : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* n := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := p0.["mul_by"] (| + n + |) in + (* TODO assignment *) + + +Definition alt_bn128_pairing_check : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..eddfd33ae3 --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,93 @@ +(* +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 byzantium.vm. +Require byzantium.vm.gas. +Require byzantium.vm.memory. + +Definition ecrecover : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_ECRECOVER + |) in + let* message_hash_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* message_hash := ethereum.crypto.hash.Hash32 (| + message_hash_bytes + |) in + let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + address, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..ae43b03308 --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/identity.v @@ -0,0 +1,36 @@ +(* +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 byzantium.vm. +Require byzantium.vm.gas. + +Definition identity : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..73f908e4b2 --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/mapping.v @@ -0,0 +1,22 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require byzantium.fork_types. +Require byzantium.vm.precompiled_contracts.alt_bn128. +Require byzantium.vm.precompiled_contracts.ecrecover. +Require byzantium.vm.precompiled_contracts.identity. +Require byzantium.vm.precompiled_contracts.modexp. +Require byzantium.vm.precompiled_contracts.ripemd160. +Require 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..068d1d3a9f --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/modexp.v @@ -0,0 +1,202 @@ +(* +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 byzantium.vm. +Require byzantium.vm.gas. +Require byzantium.vm.memory. + +Definition modexp : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + let* data := evm.["message"].["data"] in + let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_start := (* TODO expression *) in + let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + min (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + exp_length + |) + |) + |) in + do* vm.gas.charge_gas (| + evm, + gas_cost (| + base_length, + modulus_length, + exp_length, + exp_head + |) + |) in + (* TODO statement *) + let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + base_length + |) + |) in + let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + exp_length + |) + |) in + let* modulus_start := (* TODO expression *) in + let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + modulus_start, + modulus_length + |) + |) in + (* TODO statement *) + + +Definition complexity : M unit := + (* + 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. + *) + let* max_length := max (| + ethereum_types.numeric.Uint (| + base_length + |), + ethereum_types.numeric.Uint (| + modulus_length + |) + |) in + (* TODO statement *) + + +Definition iterations : M unit := + (* + 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 *) + + +Definition gas_cost : M unit := + (* + 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. + *) + let* multiplication_complexity := complexity (| + base_length, + modulus_length + |) in + let* iteration_count := iterations (| + exponent_length, + exponent_head + |) in + let* cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..bc5e73dd3c --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,42 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + let* hash_bytes := hashlib.["new"] (| + (* TODO expression *), + data + |).["digest"] (| + + |) in + let* padded_hash := left_pad_zero_bytes (| + hash_bytes, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..da6972d411 --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/sha256.v @@ -0,0 +1,32 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..cf779c7dd7 --- /dev/null +++ b/coq/ethereum/byzantium/vm/runtime.v @@ -0,0 +1,49 @@ +(* +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 byzantium.vm.instructions. + +Definition get_valid_jump_destinations : M unit := + (* + 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. + *) + let* valid_jump_destinations := set (| + + |) in + let* pc := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..78d6dbd3b7 --- /dev/null +++ b/coq/ethereum/byzantium/vm/stack.v @@ -0,0 +1,53 @@ +(* +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 byzantium.vm.exceptions. + +Definition pop : M unit := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + + +Definition push : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + diff --git a/coq/translation/__init__.ast b/coq/ethereum/cancun/__init__.ast similarity index 100% rename from coq/translation/__init__.ast rename to coq/ethereum/cancun/__init__.ast diff --git a/coq/translation/__init__.v b/coq/ethereum/cancun/__init__.v similarity index 100% rename from coq/translation/__init__.v rename to coq/ethereum/cancun/__init__.v diff --git a/coq/translation/blocks.ast b/coq/ethereum/cancun/blocks.ast similarity index 100% rename from coq/translation/blocks.ast rename to coq/ethereum/cancun/blocks.ast diff --git a/coq/ethereum/cancun/blocks.v b/coq/ethereum/cancun/blocks.v new file mode 100644 index 0000000000..67586a8e3d --- /dev/null +++ b/coq/ethereum/cancun/blocks.v @@ -0,0 +1,19 @@ +(* +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 ..crypto.hash. +Require cancun.fork_types. +Require 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..d3e273d743 --- /dev/null +++ b/coq/ethereum/cancun/bloom.v @@ -0,0 +1,66 @@ +(* +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 cancun.blocks. +Require cancun.fork_types. + +Definition add_to_bloom : 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. + *) + let* hash := ethereum.crypto.hash.keccak256 (| + bloom_entry + |) in + (* TODO statement *) + + +Definition logs_bloom : M unit := + (* + 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 *) + 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..137ea143f6 --- /dev/null +++ b/coq/ethereum/cancun/exceptions.v @@ -0,0 +1,6 @@ +(* +Exceptions specific to this fork. +*) + +Require typing. +Require ethereum.exceptions. diff --git a/coq/translation/fork.ast b/coq/ethereum/cancun/fork.ast similarity index 100% rename from coq/translation/fork.ast rename to coq/ethereum/cancun/fork.ast diff --git a/coq/ethereum/cancun/fork.v b/coq/ethereum/cancun/fork.v new file mode 100644 index 0000000000..9891312ba3 --- /dev/null +++ b/coq/ethereum/cancun/fork.v @@ -0,0 +1,695 @@ +(* +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 cancun.blocks. +Require cancun.bloom. +Require cancun.fork_types. +Require cancun.state. +Require cancun.transactions. +Require cancun.trie. +Require cancun.utils.hexadecimal. +Require cancun.utils.message. +Require cancun.vm. +Require cancun.vm.gas. +Require cancun.vm.interpreter. + +Definition apply_fork : M unit := + (* + 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 *) + + +Definition get_last_256_block_hashes : M unit := + (* + 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. + *) + let* recent_blocks := (* TODO expression *) in + (* TODO statement *) + let* recent_block_hashes := (* TODO expression *) in + (* TODO statement *) + let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *).["header"] + |) + |) in + do* recent_block_hashes.["append"] (| + most_recent_block_hash + |) in + (* TODO statement *) + + +Definition state_transition : 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`. + *) + let* parent_header := (* TODO expression *).["header"] in + let* excess_blob_gas := vm.gas.calculate_excess_blob_gas (| + parent_header + |) in + (* TODO statement *) + do* validate_header (| + block.["header"], + parent_header + |) in + (* TODO statement *) + let* apply_body_output := apply_body (| + chain.["state"], + get_last_256_block_hashes (| + chain + |), + block.["header"].["coinbase"], + block.["header"].["number"], + block.["header"].["base_fee_per_gas"], + block.["header"].["gas_limit"], + block.["header"].["timestamp"], + block.["header"].["prev_randao"], + block.["transactions"], + chain.["chain_id"], + block.["withdrawals"], + block.["header"].["parent_beacon_block_root"], + excess_blob_gas + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* chain.["blocks"].["append"] (| + block + |) in + (* TODO statement *) + + +Definition calculate_base_fee_per_gas : M unit := + (* + 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. + *) + let* parent_gas_target := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_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 *) + let* expected_base_fee_per_gas := calculate_base_fee_per_gas (| + header.["gas_limit"], + parent_header.["gas_limit"], + parent_header.["gas_used"], + parent_header.["base_fee_per_gas"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* block_parent_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + parent_header + |) + |) in + (* TODO statement *) + + +Definition check_transaction : M unit := + (* + 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 *) + let* sender := recover_sender (| + chain_id, + tx + |) in + let* sender_account := state.get_account (| + state, + sender + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition make_receipt : M unit := + (* + 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. + *) + let* receipt := blocks.Receipt (| + + |) in + (* TODO statement *) + + +Definition apply_body : M unit := + (* + 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. + *) + let* blob_gas_used := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* gas_available := block_gas_limit in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* beacon_block_roots_contract_code := state.get_account (| + state, + BEACON_ROOTS_ADDRESS + |).["code"] in + let* system_tx_message := vm.Message (| + + |) in + let* system_tx_env := vm.["Environment"] (| + + |) in + let* system_tx_output := vm.interpreter.process_message_call (| + system_tx_message, + system_tx_env + |) in + do* state.destroy_touched_empty_accounts (| + system_tx_env.["state"], + system_tx_output.["touched_accounts"] + |) in + (* TODO statement *) + (* TODO statement *) + let* block_gas_used := (* TODO expression *) in + let* block_logs_bloom := bloom.logs_bloom (| + block_logs + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_transaction : M unit := + (* + 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. + *) + let* sender := env.["origin"] in + let* sender_account := state.get_account (| + env.["state"], + sender + |) in + (* TODO statement *) + let* effective_gas_fee := (* TODO expression *) in + let* gas := (* TODO expression *) in + do* state.increment_nonce (| + env.["state"], + sender + |) in + let* sender_balance_after_gas_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + ethereum_types.numeric.U256 (| + sender_balance_after_gas_fee + |) + |) in + let* preaccessed_addresses := set (| + + |) in + let* preaccessed_storage_keys := set (| + + |) in + do* preaccessed_addresses.["add"] (| + env.["coinbase"] + |) in + (* TODO statement *) + let* message := utils.message.prepare_message (| + sender, + tx.["to"], + tx.["value"], + tx.["data"], + gas, + env + |) in + let* output := vm.interpreter.process_message_call (| + message, + env + |) in + let* gas_used := (* TODO expression *) in + let* gas_refund := min (| + (* TODO expression *), + ethereum_types.numeric.Uint (| + output.["refund_counter"] + |) + |) in + let* gas_refund_amount := (* TODO expression *) in + let* priority_fee_per_gas := (* TODO expression *) in + let* transaction_fee := (* TODO expression *) in + let* total_gas_used := (* TODO expression *) in + let* sender_balance_after_refund := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + sender_balance_after_refund + |) in + let* coinbase_balance_after_mining_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + do* state.destroy_touched_empty_accounts (| + env.["state"], + output.["touched_accounts"] + |) in + (* TODO statement *) + + +Definition calculate_intrinsic_cost : M unit := + (* + 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. + *) + let* data_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + let* access_list_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + + +Definition recover_sender : M unit := + (* + 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 *) + + +Definition signing_hash_pre155 : M unit := + (* + 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 *) + + +Definition signing_hash_155 : M unit := + (* + 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 *) + + +Definition signing_hash_2930 : M unit := + (* + 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 *) + + +Definition signing_hash_1559 : M unit := + (* + 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 *) + + +Definition signing_hash_4844 : M unit := + (* + 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 *) + + +Definition compute_header_hash : M unit := + (* + 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 *) + + +Definition check_gas_limit : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + diff --git a/coq/translation/fork_types.ast b/coq/ethereum/cancun/fork_types.ast similarity index 100% rename from coq/translation/fork_types.ast rename to coq/ethereum/cancun/fork_types.ast diff --git a/coq/ethereum/cancun/fork_types.v b/coq/ethereum/cancun/fork_types.v new file mode 100644 index 0000000000..14de99d5e5 --- /dev/null +++ b/coq/ethereum/cancun/fork_types.v @@ -0,0 +1,29 @@ +(* +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 ..crypto.hash. + +Definition encode_account : M unit := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + diff --git a/coq/translation/state.ast b/coq/ethereum/cancun/state.ast similarity index 100% rename from coq/translation/state.ast rename to coq/ethereum/cancun/state.ast diff --git a/coq/ethereum/cancun/state.v b/coq/ethereum/cancun/state.v new file mode 100644 index 0000000000..30fb8778e3 --- /dev/null +++ b/coq/ethereum/cancun/state.v @@ -0,0 +1,667 @@ +(* +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 cancun.blocks. +Require cancun.fork_types. +Require cancun.trie. + +Definition close_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 *) + + +Definition begin_transaction : 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* state.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + do* transient_storage.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + + +Definition commit_transaction : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + transient_storage : TransientStorage + The transient storage of the transaction. + *) + do* state.["_snapshots"].["pop"] (| + + |) in + (* TODO statement *) + do* transient_storage.["_snapshots"].["pop"] (| + + |) in + + +Definition rollback_transaction : 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 *) + + +Definition get_account : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition get_account_optional : M unit := + (* + 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. + *) + let* account := trie.trie_get (| + state.["_main_trie"], + address + |) in + (* TODO statement *) + + +Definition set_account : 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 (| + state.["_main_trie"], + address, + account + |) in + + +Definition destroy_account : 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* destroy_storage (| + state, + address + |) in + do* set_account (| + state, + address, + (* TODO expression *) + |) in + + +Definition destroy_storage : 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 *) + + +Definition mark_account_created : 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* state.["created_accounts"].["add"] (| + address + |) in + + +Definition get_storage : M unit := + (* + 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. + *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_storage : 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 *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition storage_root : M unit := + (* + 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 *) + + +Definition state_root : M unit := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition account_exists : M unit := + (* + 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 *) + + +Definition account_has_code_or_nonce : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_empty : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition account_exists_and_is_empty : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_alive : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition modify_state : M unit := + (* + Modify an `Account` in the `State`. + *) + do* set_account (| + state, + address, + ethereum_types.frozen.modify (| + get_account (| + state, + address + |), + f + |) + |) in + + +Definition move_ether : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* modify_state (| + state, + sender_address, + reduce_sender_balance + |) in + do* modify_state (| + state, + recipient_address, + increase_recipient_balance + |) in + + +Definition process_withdrawal : M unit := + (* + Increase the balance of the withdrawing account. + *) + (* TODO statement *) + do* modify_state (| + state, + wd.["address"], + increase_recipient_balance + |) in + + +Definition set_account_balance : 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* modify_state (| + state, + address, + set_balance + |) in + + +Definition touch_account : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + + +Definition increment_nonce : 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* modify_state (| + state, + address, + increase_nonce + |) in + + +Definition set_code : 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* modify_state (| + state, + address, + write_code + |) in + + +Definition get_storage_original : M unit := + (* + 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 *) + let* original_account_trie := original_trie.["get"] (| + address + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition get_transient_storage : M unit := + (* + 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. + *) + let* trie := transient_storage.["_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_transient_storage : 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. + *) + let* trie := transient_storage.["_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition destroy_touched_empty_accounts : 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 *) + diff --git a/coq/translation/transactions.ast b/coq/ethereum/cancun/transactions.ast similarity index 100% rename from coq/translation/transactions.ast rename to coq/ethereum/cancun/transactions.ast diff --git a/coq/ethereum/cancun/transactions.v b/coq/ethereum/cancun/transactions.v new file mode 100644 index 0000000000..ba22e3d536 --- /dev/null +++ b/coq/ethereum/cancun/transactions.v @@ -0,0 +1,27 @@ +(* +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 cancun.exceptions. +Require cancun.fork_types. + +Definition encode_transaction : M unit := + (* + Encode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + + +Definition decode_transaction : M unit := + (* + Decode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + diff --git a/coq/translation/trie.ast b/coq/ethereum/cancun/trie.ast similarity index 100% rename from coq/translation/trie.ast rename to coq/ethereum/cancun/trie.ast diff --git a/coq/ethereum/cancun/trie.v b/coq/ethereum/cancun/trie.v new file mode 100644 index 0000000000..5f0ab29642 --- /dev/null +++ b/coq/ethereum/cancun/trie.v @@ -0,0 +1,274 @@ +(* +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 : M unit := + (* + 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 *) + let* encoded := rlp.["encode"] (| + unencoded + |) in + (* TODO statement *) + + +Definition encode_node : M unit := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + + +Definition copy_trie : M unit := + (* + 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 *) + + +Definition trie_set : 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 *) + + +Definition trie_get : M unit := + (* + 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 *) + + +Definition common_prefix_length : M unit := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition nibble_list_to_compact : M unit := + (* + 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. + *) + let* compact := bytearray (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_nibble_list : M unit := + (* + 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. + *) + let* nibble_list := bytearray (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _prepare_trie : M unit := + (* + 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 *) + + +Definition root : M unit := + (* + 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. + *) + let* obj := _prepare_trie (| + trie, + get_storage_root + |) in + let* root_node := encode_internal_node (| + patricialize (| + obj, + Uint (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + + +Definition patricialize : M unit := + (* + 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 *) + let* arbitrary_key := next (| + iter (| + obj + |) + |) in + (* TODO statement *) + let* substring := (* TODO expression *) in + let* prefix_length := len (| + substring + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..beff4482b1 --- /dev/null +++ b/coq/ethereum/cancun/utils/__init__.v @@ -0,0 +1,4 @@ +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/translation/utils/address.ast b/coq/ethereum/cancun/utils/address.ast similarity index 100% rename from coq/translation/utils/address.ast rename to coq/ethereum/cancun/utils/address.ast diff --git a/coq/ethereum/cancun/utils/address.v b/coq/ethereum/cancun/utils/address.v new file mode 100644 index 0000000000..9bbf4aa8d6 --- /dev/null +++ b/coq/ethereum/cancun/utils/address.v @@ -0,0 +1,99 @@ +(* +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 cancun.fork_types. + +Definition to_address : M unit := + (* + 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 *) + + +Definition compute_contract_address : M unit := + (* + 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. + *) + let* computed_address := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *) + |) + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition compute_create2_contract_address : M unit := + (* + 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. + *) + let* preimage := (* TODO expression *) in + let* computed_address := ethereum.crypto.hash.keccak256 (| + preimage + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + diff --git a/coq/translation/utils/hexadecimal.ast b/coq/ethereum/cancun/utils/hexadecimal.ast similarity index 100% rename from coq/translation/utils/hexadecimal.ast rename to coq/ethereum/cancun/utils/hexadecimal.ast diff --git a/coq/ethereum/cancun/utils/hexadecimal.v b/coq/ethereum/cancun/utils/hexadecimal.v new file mode 100644 index 0000000000..3e508da3cd --- /dev/null +++ b/coq/ethereum/cancun/utils/hexadecimal.v @@ -0,0 +1,68 @@ +(* +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 cancun.fork_types. + +Definition hex_to_root : M unit := + (* + 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 *) + + +Definition hex_to_bloom : M unit := + (* + 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 *) + + +Definition hex_to_address : M unit := + (* + 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 *) + diff --git a/coq/translation/utils/message.ast b/coq/ethereum/cancun/utils/message.ast similarity index 100% rename from coq/translation/utils/message.ast rename to coq/ethereum/cancun/utils/message.ast diff --git a/coq/ethereum/cancun/utils/message.v b/coq/ethereum/cancun/utils/message.v new file mode 100644 index 0000000000..838fd3ca6b --- /dev/null +++ b/coq/ethereum/cancun/utils/message.v @@ -0,0 +1,82 @@ +(* +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 cancun.fork_types. +Require cancun.state. +Require cancun.vm. +Require cancun.vm.precompiled_contracts.mapping. +Require cancun.utils.address. + +Definition prepare_message : M unit := + (* + 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 *) + let* accessed_addresses := set (| + + |) in + do* accessed_addresses.["add"] (| + current_target + |) in + do* accessed_addresses.["add"] (| + caller + |) in + do* accessed_addresses.["update"] (| + vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS.["keys"] (| + + |) + |) in + do* accessed_addresses.["update"] (| + preaccessed_addresses + |) in + (* TODO statement *) + diff --git a/coq/translation/vm/__init__.ast b/coq/ethereum/cancun/vm/__init__.ast similarity index 100% rename from coq/translation/vm/__init__.ast rename to coq/ethereum/cancun/vm/__init__.ast diff --git a/coq/ethereum/cancun/vm/__init__.v b/coq/ethereum/cancun/vm/__init__.v new file mode 100644 index 0000000000..d124609337 --- /dev/null +++ b/coq/ethereum/cancun/vm/__init__.v @@ -0,0 +1,69 @@ +(* +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 cancun.blocks. +Require cancun.fork_types. +Require cancun.state. +Require cancun.vm.precompiled_contracts. + +Definition incorporate_child_on_success : 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* evm.["accounts_to_delete"].["update"] (| + child_evm.["accounts_to_delete"] + |) in + do* evm.["touched_accounts"].["update"] (| + child_evm.["touched_accounts"] + |) in + (* TODO statement *) + do* evm.["accessed_addresses"].["update"] (| + child_evm.["accessed_addresses"] + |) in + do* evm.["accessed_storage_keys"].["update"] (| + child_evm.["accessed_storage_keys"] + |) in + + +Definition incorporate_child_on_error : 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 *) + (* TODO statement *) + diff --git a/coq/translation/vm/exceptions.ast b/coq/ethereum/cancun/vm/exceptions.ast similarity index 100% rename from coq/translation/vm/exceptions.ast rename to coq/ethereum/cancun/vm/exceptions.ast diff --git a/coq/ethereum/cancun/vm/exceptions.v b/coq/ethereum/cancun/vm/exceptions.v new file mode 100644 index 0000000000..1784494410 --- /dev/null +++ b/coq/ethereum/cancun/vm/exceptions.v @@ -0,0 +1,15 @@ +(* +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/translation/vm/gas.ast b/coq/ethereum/cancun/vm/gas.ast similarity index 100% rename from coq/translation/vm/gas.ast rename to coq/ethereum/cancun/vm/gas.ast diff --git a/coq/ethereum/cancun/vm/gas.v b/coq/ethereum/cancun/vm/gas.v new file mode 100644 index 0000000000..a9c53398b9 --- /dev/null +++ b/coq/ethereum/cancun/vm/gas.v @@ -0,0 +1,251 @@ +(* +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 cancun.blocks. +Require cancun.transactions. +Require cancun.vm.exceptions. + +Definition charge_gas : 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 (| + int (| + amount + |) + |) + |) in + (* TODO statement *) + + +Definition calculate_memory_gas_cost : M unit := + (* + 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. + *) + let* size_in_words := (* TODO expression *) in + let* linear_cost := (* TODO expression *) in + let* quadratic_cost := (* TODO expression *) in + let* total_gas_cost := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_gas_extend_memory : M unit := + (* + 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` + *) + let* size_to_extend := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* to_be_paid := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* current_size := ethereum_types.numeric.Uint (| + len (| + memory + |) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_message_call_gas : M unit := + (* + 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` + *) + let* call_stipend := (* TODO expression *) in + (* TODO statement *) + let* gas := min (| + gas, + max_message_call_gas (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + + +Definition max_message_call_gas : M unit := + (* + 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 *) + + +Definition init_code_cost : M unit := + (* + 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 *) + + +Definition calculate_excess_blob_gas : M unit := + (* + 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. + *) + let* excess_blob_gas := ethereum_types.numeric.U64 (| + (* TODO expression *) + |) in + let* blob_gas_used := ethereum_types.numeric.U64 (| + (* TODO expression *) + |) in + (* TODO statement *) + let* parent_blob_gas := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_total_blob_gas : M unit := + (* + 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 *) + + +Definition calculate_blob_gas_price : M unit := + (* + 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 *) + + +Definition calculate_data_fee : M unit := + (* + 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 *) + diff --git a/coq/translation/vm/instructions/__init__.ast b/coq/ethereum/cancun/vm/instructions/__init__.ast similarity index 100% rename from coq/translation/vm/instructions/__init__.ast rename to coq/ethereum/cancun/vm/instructions/__init__.ast diff --git a/coq/ethereum/cancun/vm/instructions/__init__.v b/coq/ethereum/cancun/vm/instructions/__init__.v new file mode 100644 index 0000000000..b36b1ebfef --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/__init__.v @@ -0,0 +1,15 @@ +(* +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..1ae5a794a3 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/arithmetic.v @@ -0,0 +1,387 @@ +(* +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 cancun.vm.gas. +Require cancun.vm.stack. + +Definition add : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_add"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition sub : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_sub"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mul : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + let* result := x.["wrapping_mul"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition div : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |) in + let* divisor := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + quotient + |) in + (* TODO statement *) + + +Definition sdiv : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* divisor := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + quotient + |) + |) in + (* TODO statement *) + + +Definition mod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + remainder + |) in + (* TODO statement *) + + +Definition smod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* y := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + remainder + |) + |) in + (* TODO statement *) + + +Definition addmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mulmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition exp : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* base := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent_bits := exponent.["bit_length"] (| + + |) in + let* exponent_bytes := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* result := ethereum_types.numeric.U256 (| + pow (| + base, + exponent, + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signextend : 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. + + *) + let* byte_num := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..978e05422b --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/bitwise.v @@ -0,0 +1,245 @@ +(* +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 cancun.vm.gas. +Require cancun.vm.stack. + +Definition bitwise_and : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_or : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_xor : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_not : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition get_byte : 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. + + *) + let* byte_index := stack.pop (| + evm.["stack"] + |) in + let* word := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shl : 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. + *) + let* shift := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shr : 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. + *) + let* shift := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_sar : 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. + *) + let* shift := int (| + stack.pop (| + evm.["stack"] + |) + |) in + let* signed_value := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + diff --git a/coq/translation/vm/instructions/block.ast b/coq/ethereum/cancun/vm/instructions/block.ast similarity index 100% rename from coq/translation/vm/instructions/block.ast rename to coq/ethereum/cancun/vm/instructions/block.ast diff --git a/coq/ethereum/cancun/vm/instructions/block.v b/coq/ethereum/cancun/vm/instructions/block.v new file mode 100644 index 0000000000..7a939e8b86 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/block.v @@ -0,0 +1,249 @@ +(* +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 cancun.vm.gas. +Require cancun.vm.stack. + +Definition block_hash : 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`. + *) + let* block_number := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOCK_HASH + |) in + let* max_block_number := (* TODO expression *) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + + +Definition coinbase : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["coinbase"] + |) + |) in + (* TODO statement *) + + +Definition timestamp : 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 (| + evm.["stack"], + evm.["env"].["time"] + |) in + (* TODO statement *) + + +Definition number : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["number"] + |) + |) in + (* TODO statement *) + + +Definition prev_randao : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["prev_randao"] + |) + |) in + (* TODO statement *) + + +Definition gas_limit : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_limit"] + |) + |) in + (* TODO statement *) + + +Definition chain_id : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["chain_id"] + |) + |) in + (* TODO statement *) + 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..93d8d576f0 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/comparison.v @@ -0,0 +1,206 @@ +(* +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 cancun.vm.gas. +Require cancun.vm.stack. + +Definition less_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_less_than : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition greater_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_greater_than : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition equal : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition is_zero : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..f15822fe1f --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/control_flow.v @@ -0,0 +1,156 @@ +(* +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 cancun.vm.gas. +Require cancun.vm.exceptions. +Require cancun.vm.stack. + +Definition stop : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition jump : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_MID + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition jumpi : 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. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* conditional_value := stack.pop (| + evm.["stack"] + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_HIGH + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition pc : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["pc"] + |) + |) in + (* TODO statement *) + + +Definition gas_left : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + + +Definition jumpdest : 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 *) + (* TODO statement *) + diff --git a/coq/translation/vm/instructions/environment.ast b/coq/ethereum/cancun/vm/instructions/environment.ast similarity index 100% rename from coq/translation/vm/instructions/environment.ast rename to coq/ethereum/cancun/vm/instructions/environment.ast diff --git a/coq/ethereum/cancun/vm/instructions/environment.v b/coq/ethereum/cancun/vm/instructions/environment.v new file mode 100644 index 0000000000..69e3767e9f --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/environment.v @@ -0,0 +1,623 @@ +(* +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 cancun.fork_types. +Require cancun.state. +Require cancun.utils.address. +Require cancun.vm.memory. +Require cancun.vm.exceptions. +Require cancun.vm.gas. +Require cancun.vm.stack. + +Definition address : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["current_target"] + |) + |) in + (* TODO statement *) + + +Definition balance : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* balance := state.get_account (| + evm.["env"].["state"], + address + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition origin : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["origin"] + |) + |) in + (* TODO statement *) + + +Definition caller : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["caller"] + |) + |) in + (* TODO statement *) + + +Definition callvalue : 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 (| + evm.["stack"], + evm.["message"].["value"] + |) in + (* TODO statement *) + + +Definition calldataload : 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. + + *) + let* start_index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + start_index, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + value + |) + |) in + (* TODO statement *) + + +Definition calldatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["message"].["data"] + |) + |) + |) in + (* TODO statement *) + + +Definition calldatacopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* data_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + data_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition codesize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["code"] + |) + |) + |) in + (* TODO statement *) + + +Definition codecopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["code"], + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition gasprice : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_price"] + |) + |) in + (* TODO statement *) + + +Definition extcodesize : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* codesize := ethereum_types.numeric.U256 (| + len (| + state.get_account (| + evm.["env"].["state"], + address + |).["code"] + |) + |) in + do* stack.push (| + evm.["stack"], + codesize + |) in + (* TODO statement *) + + +Definition extcodecopy : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* code := state.get_account (| + evm.["env"].["state"], + address + |).["code"] in + let* value := vm.memory.buffer_read (| + code, + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition returndatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["return_data"] + |) + |) + |) in + (* TODO statement *) + + +Definition returndatacopy : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* return_data_start_position := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition extcodehash : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* account := state.get_account (| + evm.["env"].["state"], + address + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + codehash + |) in + (* TODO statement *) + + +Definition self_balance : 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 + let* balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition base_fee : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["base_fee_per_gas"] + |) + |) in + (* TODO statement *) + + +Definition blob_hash : M unit := + (* + Pushes the versioned hash at a particular index on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOBHASH_OPCODE + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + blob_hash + |) + |) in + (* TODO statement *) + + +Definition blob_base_fee : 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 + let* blob_base_fee := gas.calculate_blob_gas_price (| + evm.["env"].["excess_blob_gas"] + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256 (| + blob_base_fee + |) + |) in + (* TODO statement *) + 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..d306b4810f --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/keccak.v @@ -0,0 +1,67 @@ +(* +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 cancun.vm.gas. +Require cancun.vm.memory. +Require cancun.vm.stack. + +Definition keccak : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* word_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + let* hash := ethereum.crypto.hash.keccak256 (| + data + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + 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..c7a64b184c --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/log.v @@ -0,0 +1,61 @@ +(* +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 cancun.blocks. +Require cancun.vm.exceptions. +Require cancun.vm.gas. +Require cancun.vm.memory. +Require cancun.vm.stack. + +Definition log_n : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* topics := (* TODO expression *) in + (* TODO statement *) + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* log_entry := blocks.Log (| + + |) in + (* TODO assignment *) + (* TODO statement *) + diff --git a/coq/translation/vm/instructions/memory.ast b/coq/ethereum/cancun/vm/instructions/memory.ast similarity index 100% rename from coq/translation/vm/instructions/memory.ast rename to coq/ethereum/cancun/vm/instructions/memory.ast diff --git a/coq/ethereum/cancun/vm/instructions/memory.v b/coq/ethereum/cancun/vm/instructions/memory.v new file mode 100644 index 0000000000..5c969b84b8 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/memory.v @@ -0,0 +1,202 @@ +(* +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 cancun.vm.gas. +Require cancun.vm.memory. +Require cancun.vm.stack. + +Definition mstore : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* memory.memory_write (| + evm.["memory"], + start_position, + value + |) in + (* TODO statement *) + + +Definition mstore8 : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + (* TODO expression *) + |) in + do* memory.memory_write (| + evm.["memory"], + start_position, + normalized_bytes_value + |) in + (* TODO statement *) + + +Definition mload : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.memory_read_bytes (| + evm.["memory"], + start_position, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition msize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["memory"] + |) + |) + |) in + (* TODO statement *) + + +Definition mcopy : M unit := + (* + Copy the bytes in memory from one location to another. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* destination := stack.pop (| + evm.["stack"] + |) in + let* source := stack.pop (| + evm.["stack"] + |) in + let* length := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := memory.memory_read_bytes (| + evm.["memory"], + source, + length + |) in + do* memory.memory_write (| + evm.["memory"], + destination, + value + |) in + (* TODO statement *) + diff --git a/coq/translation/vm/instructions/stack.ast b/coq/ethereum/cancun/vm/instructions/stack.ast similarity index 100% rename from coq/translation/vm/instructions/stack.ast rename to coq/ethereum/cancun/vm/instructions/stack.ast diff --git a/coq/ethereum/cancun/vm/instructions/stack.v b/coq/ethereum/cancun/vm/instructions/stack.v new file mode 100644 index 0000000000..7ff41be559 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/stack.v @@ -0,0 +1,130 @@ +(* +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 cancun.vm.exceptions. +Require cancun.vm.gas. +Require cancun.vm.memory. + +Definition pop : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* stack.["pop"] (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BASE + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition push_n : 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 *) + let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + evm.["code"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + num_bytes + |) + |) + |) in + do* stack.["push"] (| + evm.["stack"], + data_to_push + |) in + (* TODO statement *) + + +Definition dup_n : 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 *) + let* data_to_duplicate := (* TODO expression *) in + do* stack.["push"] (| + evm.["stack"], + data_to_duplicate + |) in + (* TODO statement *) + + +Definition swap_n : 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 *) + (* TODO statement *) + diff --git a/coq/translation/vm/instructions/storage.ast b/coq/ethereum/cancun/vm/instructions/storage.ast similarity index 100% rename from coq/translation/vm/instructions/storage.ast rename to coq/ethereum/cancun/vm/instructions/storage.ast diff --git a/coq/ethereum/cancun/vm/instructions/storage.v b/coq/ethereum/cancun/vm/instructions/storage.v new file mode 100644 index 0000000000..8e44bdd9db --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/storage.v @@ -0,0 +1,157 @@ +(* +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 cancun.state. +Require cancun.vm.exceptions. +Require cancun.vm.gas. +Require cancun.vm.stack. + +Definition sload : 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. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + (* TODO statement *) + let* value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition sstore : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + (* TODO statement *) + let* original_value := state.get_storage_original (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + let* current_value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + let* gas_cost := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + do* state.set_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + + +Definition tload : 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. + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_WARM_ACCESS + |) in + let* value := state.get_transient_storage (| + evm.["env"].["transient_storage"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition tstore : M unit := + (* + Stores a value at a certain key in the current context's transient storage. + Parameters + ---------- + evm : + The current EVM frame. + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_WARM_ACCESS + |) in + (* TODO statement *) + do* state.set_transient_storage (| + evm.["env"].["transient_storage"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + diff --git a/coq/translation/vm/instructions/system.ast b/coq/ethereum/cancun/vm/instructions/system.ast similarity index 100% rename from coq/translation/vm/instructions/system.ast rename to coq/ethereum/cancun/vm/instructions/system.ast diff --git a/coq/ethereum/cancun/vm/instructions/system.v b/coq/ethereum/cancun/vm/instructions/system.v new file mode 100644 index 0000000000..d7e376c6d5 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/system.v @@ -0,0 +1,586 @@ +(* +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 cancun.fork_types. +Require cancun.state. +Require cancun.utils.address. +Require cancun.vm.exceptions. +Require cancun.vm.gas. +Require cancun.vm.memory. +Require cancun.vm.stack. + +Definition generic_create : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) in + (* TODO statement *) + do* evm.["accessed_addresses"].["add"] (| + contract_address + |) in + let* create_message_gas := gas.max_message_call_gas (| + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + let* sender_address := evm.["message"].["current_target"] in + let* sender := state.get_account (| + evm.["env"].["state"], + sender_address + |) in + (* TODO statement *) + (* TODO statement *) + do* state.increment_nonce (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |) in + let* child_message := Message (| + + |) in + let* child_evm := process_create_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + + +Definition create : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* init_code_gas := gas.init_code_cost (| + ethereum_types.numeric.Uint (| + memory_size + |) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_contract_address (| + evm.["message"].["current_target"], + state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["nonce"] + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size, + init_code_gas + |) in + (* TODO statement *) + + +Definition create2 : 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. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* salt := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* call_data_words := (* TODO expression *) in + let* init_code_gas := gas.init_code_cost (| + ethereum_types.numeric.Uint (| + memory_size + |) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_create2_contract_address (| + evm.["message"].["current_target"], + salt, + memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size, + init_code_gas + |) in + (* TODO statement *) + + +Definition return_ : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + + +Definition generic_call : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_input_start_position, + memory_input_size + |) in + let* code := state.get_account (| + evm.["env"].["state"], + code_address + |).["code"] in + let* child_message := Message (| + + |) in + let* child_evm := process_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + let* actual_output_size := min (| + memory_output_size, + ethereum_types.numeric.U256 (| + len (| + child_evm.["output"] + |) + |) + |) in + do* memory.memory_write (| + evm.["memory"], + memory_output_start_position, + (* TODO expression *) + |) in + + +Definition call : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* create_gas_cost := (* TODO expression *) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition callcode : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* to := evm.["message"].["current_target"] in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition selfdestruct : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* beneficiary := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* gas_cost := gas.GAS_SELF_DESTRUCT in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + let* originator := evm.["message"].["current_target"] in + let* originator_balance := state.get_account (| + evm.["env"].["state"], + originator + |).["balance"] in + do* state.move_ether (| + evm.["env"].["state"], + originator, + beneficiary, + originator_balance + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition delegatecall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + access_gas_cost + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + evm.["message"].["value"], + evm.["message"].["caller"], + evm.["message"].["current_target"], + code_address, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition staticcall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + access_gas_cost + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + evm.["message"].["current_target"], + to, + to, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition revert : 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. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + extend_memory.["cost"] + |) in + (* TODO statement *) + let* output := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + diff --git a/coq/translation/vm/interpreter.ast b/coq/ethereum/cancun/vm/interpreter.ast similarity index 100% rename from coq/translation/vm/interpreter.ast rename to coq/ethereum/cancun/vm/interpreter.ast diff --git a/coq/ethereum/cancun/vm/interpreter.v b/coq/ethereum/cancun/vm/interpreter.v new file mode 100644 index 0000000000..e84223f754 --- /dev/null +++ b/coq/ethereum/cancun/vm/interpreter.v @@ -0,0 +1,161 @@ +(* +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 cancun.blocks. +Require cancun.fork_types. +Require cancun.state. +Require cancun.vm. +Require cancun.vm.gas. +Require cancun.vm.precompiled_contracts.mapping. +Require cancun.vm.exceptions. +Require cancun.vm.instructions. +Require cancun.vm.runtime. + +Definition process_message_call : M unit := + (* + 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 *) + let* tx_end := ethereum.trace.TransactionEnd (| + (* TODO expression *), + evm.["output"], + evm.["error"] + |) in + do* ethereum.trace.evm_trace (| + evm, + tx_end + |) in + (* TODO statement *) + + +Definition process_create_message : M unit := + (* + 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 (| + env.["state"], + env.["transient_storage"] + |) in + do* state.destroy_storage (| + env.["state"], + message.["current_target"] + |) in + do* state.mark_account_created (| + env.["state"], + message.["current_target"] + |) in + do* state.increment_nonce (| + env.["state"], + message.["current_target"] + |) in + let* evm := process_message (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_message : M unit := + (* + 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 (| + env.["state"], + env.["transient_storage"] + |) in + do* state.touch_account (| + env.["state"], + message.["current_target"] + |) in + (* TODO statement *) + let* evm := execute_code (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition execute_code : M unit := + (* + 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 + *) + let* code := message.["code"] in + let* valid_jump_destinations := runtime.get_valid_jump_destinations (| + code + |) in + let* evm := Evm (| + + |) in + (* TODO statement *) + (* TODO statement *) + 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..94b6a44639 --- /dev/null +++ b/coq/ethereum/cancun/vm/memory.v @@ -0,0 +1,75 @@ +(* +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 : 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 *) + + +Definition memory_read_bytes : M unit := + (* + 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 *) + + +Definition buffer_read : M unit := + (* + 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 *) + diff --git a/coq/translation/vm/precompiled_contracts/__init__.ast b/coq/ethereum/cancun/vm/precompiled_contracts/__init__.ast similarity index 100% rename from coq/translation/vm/precompiled_contracts/__init__.ast rename to coq/ethereum/cancun/vm/precompiled_contracts/__init__.ast 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..9d793f6554 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/__init__.v @@ -0,0 +1,16 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require 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..d7cb159a53 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,187 @@ +(* +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 cancun.vm. +Require cancun.vm.gas. +Require cancun.vm.memory. +Require cancun.vm.exceptions. + +Definition alt_bn128_add : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* x1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x1_bytes + |) + |) in + let* y1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y1_bytes + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := (* TODO expression *) in + (* TODO assignment *) + + +Definition alt_bn128_mul : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* n := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := p0.["mul_by"] (| + n + |) in + (* TODO assignment *) + + +Definition alt_bn128_pairing_check : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..4808403d8f --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,41 @@ +(* +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 cancun.vm. +Require cancun.vm.gas. +Require cancun.vm.exceptions. + +Definition blake2f : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + (* TODO statement *) + let* blake2b := ethereum.crypto.blake2.Blake2b (| + + |) in + (* TODO assignment *) + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + 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..3c1b792ab4 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,93 @@ +(* +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 cancun.vm. +Require cancun.vm.gas. +Require cancun.vm.memory. + +Definition ecrecover : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_ECRECOVER + |) in + let* message_hash_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* message_hash := ethereum.crypto.hash.Hash32 (| + message_hash_bytes + |) in + let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + address, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..3b7740c3da --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/identity.v @@ -0,0 +1,36 @@ +(* +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 cancun.vm. +Require cancun.vm.gas. + +Definition identity : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + diff --git a/coq/translation/vm/precompiled_contracts/mapping.ast b/coq/ethereum/cancun/vm/precompiled_contracts/mapping.ast similarity index 100% rename from coq/translation/vm/precompiled_contracts/mapping.ast rename to coq/ethereum/cancun/vm/precompiled_contracts/mapping.ast 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..7dd353ccee --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/mapping.v @@ -0,0 +1,24 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require cancun.fork_types. +Require cancun.vm.precompiled_contracts.alt_bn128. +Require cancun.vm.precompiled_contracts.blake2f. +Require cancun.vm.precompiled_contracts.ecrecover. +Require cancun.vm.precompiled_contracts.identity. +Require cancun.vm.precompiled_contracts.modexp. +Require cancun.vm.precompiled_contracts.point_evaluation. +Require cancun.vm.precompiled_contracts.ripemd160. +Require 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..e885e634b8 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/modexp.v @@ -0,0 +1,203 @@ +(* +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 cancun.vm. +Require cancun.vm.gas. +Require cancun.vm.memory. + +Definition modexp : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + let* data := evm.["message"].["data"] in + let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_start := (* TODO expression *) in + let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + min (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + exp_length + |) + |) + |) in + do* vm.gas.charge_gas (| + evm, + gas_cost (| + base_length, + modulus_length, + exp_length, + exp_head + |) + |) in + (* TODO statement *) + let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + base_length + |) + |) in + let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + exp_length + |) + |) in + let* modulus_start := (* TODO expression *) in + let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + modulus_start, + modulus_length + |) + |) in + (* TODO statement *) + + +Definition complexity : M unit := + (* + 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. + *) + let* max_length := max (| + ethereum_types.numeric.Uint (| + base_length + |), + ethereum_types.numeric.Uint (| + modulus_length + |) + |) in + let* words := (* TODO expression *) in + (* TODO statement *) + + +Definition iterations : M unit := + (* + 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 *) + + +Definition gas_cost : M unit := + (* + 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. + *) + let* multiplication_complexity := complexity (| + base_length, + modulus_length + |) in + let* iteration_count := iterations (| + exponent_length, + exponent_head + |) in + let* cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + diff --git a/coq/translation/vm/precompiled_contracts/point_evaluation.ast b/coq/ethereum/cancun/vm/precompiled_contracts/point_evaluation.ast similarity index 100% rename from coq/translation/vm/precompiled_contracts/point_evaluation.ast rename to coq/ethereum/cancun/vm/precompiled_contracts/point_evaluation.ast 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..a26fdde533 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/point_evaluation.v @@ -0,0 +1,56 @@ +(* +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 cancun.vm. +Require cancun.vm.exceptions. +Require cancun.vm.gas. + +Definition point_evaluation : 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. + + *) + let* data := evm.["message"].["data"] in + (* TODO statement *) + let* versioned_hash := (* TODO expression *) in + let* z := ethereum_types.bytes.Bytes32 (| + (* TODO expression *) + |) in + let* y := ethereum_types.bytes.Bytes32 (| + (* TODO expression *) + |) in + let* commitment := ethereum.crypto.kzg.KZGCommitment (| + (* TODO expression *) + |) in + let* proof := ethereum_types.bytes.Bytes48 (| + (* TODO expression *) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_POINT_EVALUATION + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + 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..bc5e73dd3c --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,42 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + let* hash_bytes := hashlib.["new"] (| + (* TODO expression *), + data + |).["digest"] (| + + |) in + let* padded_hash := left_pad_zero_bytes (| + hash_bytes, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..da6972d411 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/sha256.v @@ -0,0 +1,32 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..7ec918f688 --- /dev/null +++ b/coq/ethereum/cancun/vm/runtime.v @@ -0,0 +1,49 @@ +(* +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 cancun.vm.instructions. + +Definition get_valid_jump_destinations : M unit := + (* + 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. + *) + let* valid_jump_destinations := set (| + + |) in + let* pc := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..96481b4af1 --- /dev/null +++ b/coq/ethereum/cancun/vm/stack.v @@ -0,0 +1,53 @@ +(* +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 cancun.vm.exceptions. + +Definition pop : M unit := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + + +Definition push : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + 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..440e1bea53 --- /dev/null +++ b/coq/ethereum/constantinople/__init__.v @@ -0,0 +1,7 @@ +(* +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..b9f11c596c --- /dev/null +++ b/coq/ethereum/constantinople/blocks.v @@ -0,0 +1,19 @@ +(* +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 ..crypto.hash. +Require constantinople.fork_types. +Require 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..fb43b89d06 --- /dev/null +++ b/coq/ethereum/constantinople/bloom.v @@ -0,0 +1,66 @@ +(* +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 constantinople.blocks. +Require constantinople.fork_types. + +Definition add_to_bloom : 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. + *) + let* hash := ethereum.crypto.hash.keccak256 (| + bloom_entry + |) in + (* TODO statement *) + + +Definition logs_bloom : M unit := + (* + 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 *) + 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..e1d424bb04 --- /dev/null +++ b/coq/ethereum/constantinople/fork.v @@ -0,0 +1,760 @@ +(* +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 constantinople.blocks. +Require constantinople.bloom. +Require constantinople.fork_types. +Require constantinople.state. +Require constantinople.transactions. +Require constantinople.trie. +Require constantinople.utils.message. +Require constantinople.vm.interpreter. + +Definition apply_fork : M unit := + (* + 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 *) + + +Definition get_last_256_block_hashes : M unit := + (* + 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. + *) + let* recent_blocks := (* TODO expression *) in + (* TODO statement *) + let* recent_block_hashes := (* TODO expression *) in + (* TODO statement *) + let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *).["header"] + |) + |) in + do* recent_block_hashes.["append"] (| + most_recent_block_hash + |) in + (* TODO statement *) + + +Definition state_transition : 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`. + *) + let* parent_header := (* TODO expression *).["header"] in + do* validate_header (| + block.["header"], + parent_header + |) in + do* validate_ommers (| + block.["ommers"], + block.["header"], + chain + |) in + let* apply_body_output := apply_body (| + chain.["state"], + get_last_256_block_hashes (| + chain + |), + block.["header"].["coinbase"], + block.["header"].["number"], + block.["header"].["gas_limit"], + block.["header"].["timestamp"], + block.["header"].["difficulty"], + block.["transactions"], + block.["ommers"], + chain.["chain_id"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* chain.["blocks"].["append"] (| + block + |) in + (* TODO statement *) + + +Definition validate_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 + *) + let* parent_has_ommers := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* block_difficulty := calculate_block_difficulty (| + header.["number"], + header.["timestamp"], + parent_header.["timestamp"], + parent_header.["difficulty"], + parent_has_ommers + |) in + (* TODO statement *) + let* block_parent_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + parent_header + |) + |) in + (* TODO statement *) + do* validate_proof_of_work (| + header + |) in + + +Definition generate_header_hash_for_pow : M unit := + (* + 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. + *) + let* header_data_without_pow_artefacts := (* TODO expression *) in + (* TODO statement *) + + +Definition validate_proof_of_work : 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. + *) + let* header_hash := generate_header_hash_for_pow (| + header + |) in + let* cache := ethereum.ethash.generate_cache (| + header.["number"] + |) in + (* TODO assignment *) + (* TODO statement *) + let* limit := (* TODO expression *) in + (* TODO statement *) + + +Definition check_transaction : M unit := + (* + 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 *) + let* sender_address := recover_sender (| + chain_id, + tx + |) in + (* TODO statement *) + + +Definition make_receipt : M unit := + (* + 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. + *) + let* receipt := blocks.Receipt (| + + |) in + (* TODO statement *) + + +Definition apply_body : M unit := + (* + 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. + *) + let* gas_available := block_gas_limit in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* pay_rewards (| + state, + block_number, + coinbase, + ommers + |) in + let* block_gas_used := (* TODO expression *) in + let* block_logs_bloom := bloom.logs_bloom (| + block_logs + |) in + (* TODO statement *) + + +Definition validate_ommers : 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. + *) + let* block_hash := rlp.["rlp_hash"] (| + block_header + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* ommers_hashes := (* TODO expression *) in + (* TODO statement *) + let* recent_canonical_blocks := (* TODO expression *) in + let* recent_canonical_block_hashes := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition pay_rewards : 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. + *) + let* ommer_count := ethereum_types.numeric.U256 (| + len (| + ommers + |) + |) in + let* miner_reward := (* TODO expression *) in + do* state.create_ether (| + state, + coinbase, + miner_reward + |) in + (* TODO statement *) + + +Definition process_transaction : M unit := + (* + 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 *) + let* sender := env.["origin"] in + let* sender_account := state.get_account (| + env.["state"], + sender + |) in + let* gas_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* gas := (* TODO expression *) in + do* state.increment_nonce (| + env.["state"], + sender + |) in + let* sender_balance_after_gas_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + ethereum_types.numeric.U256 (| + sender_balance_after_gas_fee + |) + |) in + let* message := utils.message.prepare_message (| + sender, + tx.["to"], + tx.["value"], + tx.["data"], + gas, + env + |) in + let* output := vm.interpreter.process_message_call (| + message, + env + |) in + let* gas_used := (* TODO expression *) in + let* gas_refund := min (| + (* TODO expression *), + ethereum_types.numeric.Uint (| + output.["refund_counter"] + |) + |) in + let* gas_refund_amount := (* TODO expression *) in + let* transaction_fee := (* TODO expression *) in + let* total_gas_used := (* TODO expression *) in + let* sender_balance_after_refund := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + sender_balance_after_refund + |) in + let* coinbase_balance_after_mining_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_transaction : M unit := + (* + 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 *) + + +Definition calculate_intrinsic_cost : M unit := + (* + 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. + *) + let* data_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition recover_sender : M unit := + (* + 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 *) + + +Definition signing_hash_pre155 : M unit := + (* + 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 *) + + +Definition signing_hash_155 : M unit := + (* + 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 *) + + +Definition compute_header_hash : M unit := + (* + 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 *) + + +Definition check_gas_limit : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_block_difficulty : M unit := + (* + 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. + *) + let* offset := (* TODO expression *) in + let* difficulty := (* TODO expression *) in + let* num_bomb_periods := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..14de99d5e5 --- /dev/null +++ b/coq/ethereum/constantinople/fork_types.v @@ -0,0 +1,29 @@ +(* +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 ..crypto.hash. + +Definition encode_account : M unit := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + 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..bbfa643372 --- /dev/null +++ b/coq/ethereum/constantinople/state.v @@ -0,0 +1,543 @@ +(* +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 constantinople.fork_types. +Require constantinople.trie. + +Definition close_state : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition begin_transaction : 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* state.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + + +Definition commit_transaction : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* state.["_snapshots"].["pop"] (| + + |) in + + +Definition rollback_transaction : 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 *) + + +Definition get_account : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition get_account_optional : M unit := + (* + 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. + *) + let* account := trie.trie_get (| + state.["_main_trie"], + address + |) in + (* TODO statement *) + + +Definition set_account : 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 (| + state.["_main_trie"], + address, + account + |) in + + +Definition destroy_account : 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* destroy_storage (| + state, + address + |) in + do* set_account (| + state, + address, + (* TODO expression *) + |) in + + +Definition destroy_storage : 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 *) + + +Definition get_storage : M unit := + (* + 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. + *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_storage : 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 *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition storage_root : M unit := + (* + 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 *) + + +Definition state_root : M unit := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition account_exists : M unit := + (* + 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 *) + + +Definition account_has_code_or_nonce : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_empty : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition account_exists_and_is_empty : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_alive : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition modify_state : M unit := + (* + Modify an `Account` in the `State`. + *) + do* set_account (| + state, + address, + ethereum_types.frozen.modify (| + get_account (| + state, + address + |), + f + |) + |) in + + +Definition move_ether : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* modify_state (| + state, + sender_address, + reduce_sender_balance + |) in + do* modify_state (| + state, + recipient_address, + increase_recipient_balance + |) in + + +Definition set_account_balance : 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* modify_state (| + state, + address, + set_balance + |) in + + +Definition touch_account : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + + +Definition increment_nonce : 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* modify_state (| + state, + address, + increase_nonce + |) in + + +Definition set_code : 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* modify_state (| + state, + address, + write_code + |) in + + +Definition create_ether : 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* modify_state (| + state, + address, + increase_balance + |) in + 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..f9651a485a --- /dev/null +++ b/coq/ethereum/constantinople/transactions.v @@ -0,0 +1,12 @@ +(* +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 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..548de91e1c --- /dev/null +++ b/coq/ethereum/constantinople/trie.v @@ -0,0 +1,274 @@ +(* +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 : M unit := + (* + 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 *) + let* encoded := rlp.["encode"] (| + unencoded + |) in + (* TODO statement *) + + +Definition encode_node : M unit := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + + +Definition copy_trie : M unit := + (* + 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 *) + + +Definition trie_set : 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 *) + + +Definition trie_get : M unit := + (* + 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 *) + + +Definition common_prefix_length : M unit := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition nibble_list_to_compact : M unit := + (* + 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. + *) + let* compact := bytearray (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_nibble_list : M unit := + (* + 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. + *) + let* nibble_list := bytearray (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _prepare_trie : M unit := + (* + 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 *) + + +Definition root : M unit := + (* + 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. + *) + let* obj := _prepare_trie (| + trie, + get_storage_root + |) in + let* root_node := encode_internal_node (| + patricialize (| + obj, + Uint (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + + +Definition patricialize : M unit := + (* + 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 *) + let* arbitrary_key := next (| + iter (| + obj + |) + |) in + (* TODO statement *) + let* substring := (* TODO expression *) in + let* prefix_length := len (| + substring + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..beff4482b1 --- /dev/null +++ b/coq/ethereum/constantinople/utils/__init__.v @@ -0,0 +1,4 @@ +(* +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..da7da274c1 --- /dev/null +++ b/coq/ethereum/constantinople/utils/address.v @@ -0,0 +1,99 @@ +(* +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 constantinople.fork_types. + +Definition to_address : M unit := + (* + 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 *) + + +Definition compute_contract_address : M unit := + (* + 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. + *) + let* computed_address := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *) + |) + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition compute_create2_contract_address : M unit := + (* + 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. + *) + let* preimage := (* TODO expression *) in + let* computed_address := ethereum.crypto.hash.keccak256 (| + preimage + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + 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..bc629eb420 --- /dev/null +++ b/coq/ethereum/constantinople/utils/hexadecimal.v @@ -0,0 +1,68 @@ +(* +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 constantinople.fork_types. + +Definition hex_to_root : M unit := + (* + 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 *) + + +Definition hex_to_bloom : M unit := + (* + 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 *) + + +Definition hex_to_address : M unit := + (* + 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 *) + 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..c3cd234a4f --- /dev/null +++ b/coq/ethereum/constantinople/utils/message.v @@ -0,0 +1,59 @@ +(* +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 constantinople.fork_types. +Require constantinople.state. +Require constantinople.vm. +Require constantinople.utils.address. + +Definition prepare_message : M unit := + (* + 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 *) + 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..9cb6aadbae --- /dev/null +++ b/coq/ethereum/constantinople/vm/__init__.v @@ -0,0 +1,63 @@ +(* +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 constantinople.blocks. +Require constantinople.fork_types. +Require constantinople.state. +Require constantinople.vm.precompiled_contracts. + +Definition incorporate_child_on_success : 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* evm.["accounts_to_delete"].["update"] (| + child_evm.["accounts_to_delete"] + |) in + do* evm.["touched_accounts"].["update"] (| + child_evm.["touched_accounts"] + |) in + (* TODO statement *) + + +Definition incorporate_child_on_error : 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 *) + (* TODO statement *) + 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..1784494410 --- /dev/null +++ b/coq/ethereum/constantinople/vm/exceptions.v @@ -0,0 +1,15 @@ +(* +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..1f6a2740bc --- /dev/null +++ b/coq/ethereum/constantinople/vm/gas.v @@ -0,0 +1,151 @@ +(* +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 constantinople.vm.exceptions. + +Definition charge_gas : 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 (| + int (| + amount + |) + |) + |) in + (* TODO statement *) + + +Definition calculate_memory_gas_cost : M unit := + (* + 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. + *) + let* size_in_words := (* TODO expression *) in + let* linear_cost := (* TODO expression *) in + let* quadratic_cost := (* TODO expression *) in + let* total_gas_cost := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_gas_extend_memory : M unit := + (* + 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` + *) + let* size_to_extend := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* to_be_paid := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* current_size := ethereum_types.numeric.Uint (| + len (| + memory + |) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_message_call_gas : M unit := + (* + 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` + *) + let* call_stipend := (* TODO expression *) in + (* TODO statement *) + let* gas := min (| + gas, + max_message_call_gas (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + + +Definition max_message_call_gas : M unit := + (* + 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 *) + 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..b36b1ebfef --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/__init__.v @@ -0,0 +1,15 @@ +(* +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..d11bf62de0 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/arithmetic.v @@ -0,0 +1,387 @@ +(* +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 constantinople.vm.gas. +Require constantinople.vm.stack. + +Definition add : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_add"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition sub : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_sub"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mul : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + let* result := x.["wrapping_mul"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition div : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |) in + let* divisor := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + quotient + |) in + (* TODO statement *) + + +Definition sdiv : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* divisor := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + quotient + |) + |) in + (* TODO statement *) + + +Definition mod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + remainder + |) in + (* TODO statement *) + + +Definition smod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* y := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + remainder + |) + |) in + (* TODO statement *) + + +Definition addmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mulmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition exp : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* base := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent_bits := exponent.["bit_length"] (| + + |) in + let* exponent_bytes := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* result := ethereum_types.numeric.U256 (| + pow (| + base, + exponent, + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signextend : 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. + + *) + let* byte_num := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..b932c046a2 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/bitwise.v @@ -0,0 +1,245 @@ +(* +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 constantinople.vm.gas. +Require constantinople.vm.stack. + +Definition bitwise_and : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_or : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_xor : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_not : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition get_byte : 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. + + *) + let* byte_index := stack.pop (| + evm.["stack"] + |) in + let* word := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shl : 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. + *) + let* shift := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shr : 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. + *) + let* shift := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_sar : 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. + *) + let* shift := int (| + stack.pop (| + evm.["stack"] + |) + |) in + let* signed_value := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..477579821c --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/block.v @@ -0,0 +1,183 @@ +(* +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 constantinople.vm.gas. +Require constantinople.vm.stack. + +Definition block_hash : 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. + + *) + let* block_number := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOCK_HASH + |) in + let* max_block_number := (* TODO expression *) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + + +Definition coinbase : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["coinbase"] + |) + |) in + (* TODO statement *) + + +Definition timestamp : 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 (| + evm.["stack"], + evm.["env"].["time"] + |) in + (* TODO statement *) + + +Definition number : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["number"] + |) + |) in + (* TODO statement *) + + +Definition difficulty : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["difficulty"] + |) + |) in + (* TODO statement *) + + +Definition gas_limit : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_limit"] + |) + |) in + (* TODO statement *) + 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..ba89c5e0d2 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/comparison.v @@ -0,0 +1,206 @@ +(* +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 constantinople.vm.gas. +Require constantinople.vm.stack. + +Definition less_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_less_than : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition greater_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_greater_than : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition equal : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition is_zero : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..643fc57e22 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/control_flow.v @@ -0,0 +1,156 @@ +(* +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 constantinople.vm.gas. +Require constantinople.vm.exceptions. +Require constantinople.vm.stack. + +Definition stop : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition jump : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_MID + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition jumpi : 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. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* conditional_value := stack.pop (| + evm.["stack"] + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_HIGH + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition pc : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["pc"] + |) + |) in + (* TODO statement *) + + +Definition gas_left : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + + +Definition jumpdest : 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 *) + (* TODO statement *) + 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..619b4d41e7 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/environment.v @@ -0,0 +1,530 @@ +(* +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 constantinople.fork_types. +Require constantinople.state. +Require constantinople.utils.address. +Require constantinople.vm.memory. +Require constantinople.vm.exceptions. +Require constantinople.vm.gas. +Require constantinople.vm.stack. + +Definition address : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["current_target"] + |) + |) in + (* TODO statement *) + + +Definition balance : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BALANCE + |) in + let* balance := state.get_account (| + evm.["env"].["state"], + address + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition origin : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["origin"] + |) + |) in + (* TODO statement *) + + +Definition caller : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["caller"] + |) + |) in + (* TODO statement *) + + +Definition callvalue : 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 (| + evm.["stack"], + evm.["message"].["value"] + |) in + (* TODO statement *) + + +Definition calldataload : 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. + + *) + let* start_index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + start_index, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + value + |) + |) in + (* TODO statement *) + + +Definition calldatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["message"].["data"] + |) + |) + |) in + (* TODO statement *) + + +Definition calldatacopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* data_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + data_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition codesize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["code"] + |) + |) + |) in + (* TODO statement *) + + +Definition codecopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["code"], + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition gasprice : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_price"] + |) + |) in + (* TODO statement *) + + +Definition extcodesize : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_EXTERNAL + |) in + let* codesize := ethereum_types.numeric.U256 (| + len (| + state.get_account (| + evm.["env"].["state"], + address + |).["code"] + |) + |) in + do* stack.push (| + evm.["stack"], + codesize + |) in + (* TODO statement *) + + +Definition extcodecopy : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* code := state.get_account (| + evm.["env"].["state"], + address + |).["code"] in + let* value := vm.memory.buffer_read (| + code, + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition returndatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["return_data"] + |) + |) + |) in + (* TODO statement *) + + +Definition returndatacopy : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* return_data_start_position := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition extcodehash : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_CODE_HASH + |) in + let* account := state.get_account (| + evm.["env"].["state"], + address + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + codehash + |) in + (* TODO statement *) + 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..03d2ae2277 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/keccak.v @@ -0,0 +1,67 @@ +(* +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 constantinople.vm.gas. +Require constantinople.vm.memory. +Require constantinople.vm.stack. + +Definition keccak : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* word_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + let* hash := ethereum.crypto.hash.keccak256 (| + data + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + 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..08ad7b39f8 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/log.v @@ -0,0 +1,61 @@ +(* +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 constantinople.blocks. +Require constantinople.vm.exceptions. +Require constantinople.vm.gas. +Require constantinople.vm.memory. +Require constantinople.vm.stack. + +Definition log_n : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* topics := (* TODO expression *) in + (* TODO statement *) + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* log_entry := blocks.Log (| + + |) in + (* TODO assignment *) + (* TODO statement *) + 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..63b87f26a6 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/memory.v @@ -0,0 +1,158 @@ +(* +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 constantinople.vm.gas. +Require constantinople.vm.memory. +Require constantinople.vm.stack. + +Definition mstore : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* memory.memory_write (| + evm.["memory"], + start_position, + value + |) in + (* TODO statement *) + + +Definition mstore8 : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + (* TODO expression *) + |) in + do* memory.memory_write (| + evm.["memory"], + start_position, + normalized_bytes_value + |) in + (* TODO statement *) + + +Definition mload : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.memory_read_bytes (| + evm.["memory"], + start_position, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition msize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["memory"] + |) + |) + |) in + (* TODO statement *) + 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..a895f423d0 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/stack.v @@ -0,0 +1,133 @@ +(* +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 constantinople.vm.exceptions. +Require constantinople.vm.gas. +Require constantinople.vm.memory. + +Definition pop : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* stack.["pop"] (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BASE + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition push_n : 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 + let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + evm.["code"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + num_bytes + |) + |) + |) in + do* stack.["push"] (| + evm.["stack"], + data_to_push + |) in + (* TODO statement *) + + +Definition dup_n : 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 *) + let* data_to_duplicate := (* TODO expression *) in + do* stack.["push"] (| + evm.["stack"], + data_to_duplicate + |) in + (* TODO statement *) + + +Definition swap_n : 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 *) + (* TODO statement *) + 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..0e5ea6a23e --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/storage.v @@ -0,0 +1,90 @@ +(* +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 constantinople.state. +Require constantinople.vm.exceptions. +Require constantinople.vm.gas. +Require constantinople.vm.stack. + +Definition sload : 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. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_SLOAD + |) in + let* value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition sstore : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + let* current_value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + do* state.set_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + 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..adcc7f10c0 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/system.v @@ -0,0 +1,581 @@ +(* +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 constantinople.fork_types. +Require constantinople.state. +Require constantinople.utils.address. +Require constantinople.vm.exceptions. +Require constantinople.vm.gas. +Require constantinople.vm.memory. +Require constantinople.vm.stack. + +Definition generic_create : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + let* create_message_gas := gas.max_message_call_gas (| + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + let* sender_address := evm.["message"].["current_target"] in + let* sender := state.get_account (| + evm.["env"].["state"], + sender_address + |) in + (* TODO statement *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) in + do* state.increment_nonce (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |) in + let* child_message := Message (| + + |) in + let* child_evm := process_create_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + + +Definition create : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_contract_address (| + evm.["message"].["current_target"], + state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["nonce"] + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size + |) in + (* TODO statement *) + + +Definition create2 : 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. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* salt := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* call_data_words := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_create2_contract_address (| + evm.["message"].["current_target"], + salt, + memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size + |) in + (* TODO statement *) + + +Definition return_ : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + + +Definition generic_call : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_input_start_position, + memory_input_size + |) in + let* code := state.get_account (| + evm.["env"].["state"], + code_address + |).["code"] in + let* child_message := Message (| + + |) in + let* child_evm := process_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + let* actual_output_size := min (| + memory_output_size, + ethereum_types.numeric.U256 (| + len (| + child_evm.["output"] + |) + |) + |) in + do* memory.memory_write (| + evm.["memory"], + memory_output_start_position, + (* TODO expression *) + |) in + + +Definition call : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* create_gas_cost := (* TODO expression *) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition callcode : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* to := evm.["message"].["current_target"] in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition selfdestruct : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* beneficiary := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* gas_cost := gas.GAS_SELF_DESTRUCT in + (* TODO statement *) + let* originator := evm.["message"].["current_target"] in + let* refunded_accounts := evm.["accounts_to_delete"] in + let* parent_evm := evm.["message"].["parent_evm"] in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + let* beneficiary_balance := state.get_account (| + evm.["env"].["state"], + beneficiary + |).["balance"] in + let* originator_balance := state.get_account (| + evm.["env"].["state"], + originator + |).["balance"] in + do* state.set_account_balance (| + evm.["env"].["state"], + beneficiary, + (* TODO expression *) + |) in + do* state.set_account_balance (| + evm.["env"].["state"], + originator, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* evm.["accounts_to_delete"].["add"] (| + originator + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition delegatecall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + gas.GAS_CALL + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + evm.["message"].["value"], + evm.["message"].["caller"], + evm.["message"].["current_target"], + code_address, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition staticcall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + gas.GAS_CALL + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + evm.["message"].["current_target"], + to, + to, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition revert : 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. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + extend_memory.["cost"] + |) in + (* TODO statement *) + let* output := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + 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..45f11e60ca --- /dev/null +++ b/coq/ethereum/constantinople/vm/interpreter.v @@ -0,0 +1,155 @@ +(* +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 constantinople.blocks. +Require constantinople.fork_types. +Require constantinople.state. +Require constantinople.vm. +Require constantinople.vm.gas. +Require constantinople.vm.precompiled_contracts.mapping. +Require constantinople.vm.exceptions. +Require constantinople.vm.instructions. +Require constantinople.vm.runtime. + +Definition process_message_call : M unit := + (* + 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 *) + let* tx_end := ethereum.trace.TransactionEnd (| + (* TODO expression *), + evm.["output"], + evm.["error"] + |) in + do* ethereum.trace.evm_trace (| + evm, + tx_end + |) in + (* TODO statement *) + + +Definition process_create_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.destroy_storage (| + env.["state"], + message.["current_target"] + |) in + do* state.increment_nonce (| + env.["state"], + message.["current_target"] + |) in + let* evm := process_message (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.touch_account (| + env.["state"], + message.["current_target"] + |) in + (* TODO statement *) + let* evm := execute_code (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition execute_code : M unit := + (* + 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 + *) + let* code := message.["code"] in + let* valid_jump_destinations := runtime.get_valid_jump_destinations (| + code + |) in + let* evm := Evm (| + + |) in + (* TODO statement *) + (* TODO statement *) + 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..94b6a44639 --- /dev/null +++ b/coq/ethereum/constantinople/vm/memory.v @@ -0,0 +1,75 @@ +(* +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 : 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 *) + + +Definition memory_read_bytes : M unit := + (* + 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 *) + + +Definition buffer_read : M unit := + (* + 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 *) + 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..fa937a542c --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/__init__.v @@ -0,0 +1,16 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require 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..06b8362a0d --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,187 @@ +(* +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 constantinople.vm. +Require constantinople.vm.gas. +Require constantinople.vm.memory. +Require constantinople.vm.exceptions. + +Definition alt_bn128_add : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* x1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x1_bytes + |) + |) in + let* y1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y1_bytes + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := (* TODO expression *) in + (* TODO assignment *) + + +Definition alt_bn128_mul : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* n := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := p0.["mul_by"] (| + n + |) in + (* TODO assignment *) + + +Definition alt_bn128_pairing_check : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..87810b0f2f --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,93 @@ +(* +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 constantinople.vm. +Require constantinople.vm.gas. +Require constantinople.vm.memory. + +Definition ecrecover : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_ECRECOVER + |) in + let* message_hash_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* message_hash := ethereum.crypto.hash.Hash32 (| + message_hash_bytes + |) in + let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + address, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..484508fbe5 --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/identity.v @@ -0,0 +1,36 @@ +(* +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 constantinople.vm. +Require constantinople.vm.gas. + +Definition identity : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..0d67cdb857 --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/mapping.v @@ -0,0 +1,22 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require constantinople.fork_types. +Require constantinople.vm.precompiled_contracts.alt_bn128. +Require constantinople.vm.precompiled_contracts.ecrecover. +Require constantinople.vm.precompiled_contracts.identity. +Require constantinople.vm.precompiled_contracts.modexp. +Require constantinople.vm.precompiled_contracts.ripemd160. +Require 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..679c3bf4c6 --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/modexp.v @@ -0,0 +1,202 @@ +(* +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 constantinople.vm. +Require constantinople.vm.gas. +Require constantinople.vm.memory. + +Definition modexp : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + let* data := evm.["message"].["data"] in + let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_start := (* TODO expression *) in + let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + min (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + exp_length + |) + |) + |) in + do* vm.gas.charge_gas (| + evm, + gas_cost (| + base_length, + modulus_length, + exp_length, + exp_head + |) + |) in + (* TODO statement *) + let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + base_length + |) + |) in + let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + exp_length + |) + |) in + let* modulus_start := (* TODO expression *) in + let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + modulus_start, + modulus_length + |) + |) in + (* TODO statement *) + + +Definition complexity : M unit := + (* + 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. + *) + let* max_length := max (| + ethereum_types.numeric.Uint (| + base_length + |), + ethereum_types.numeric.Uint (| + modulus_length + |) + |) in + (* TODO statement *) + + +Definition iterations : M unit := + (* + 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 *) + + +Definition gas_cost : M unit := + (* + 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. + *) + let* multiplication_complexity := complexity (| + base_length, + modulus_length + |) in + let* iteration_count := iterations (| + exponent_length, + exponent_head + |) in + let* cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..bc5e73dd3c --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,42 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + let* hash_bytes := hashlib.["new"] (| + (* TODO expression *), + data + |).["digest"] (| + + |) in + let* padded_hash := left_pad_zero_bytes (| + hash_bytes, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..da6972d411 --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/sha256.v @@ -0,0 +1,32 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..1888cf7bb2 --- /dev/null +++ b/coq/ethereum/constantinople/vm/runtime.v @@ -0,0 +1,49 @@ +(* +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 constantinople.vm.instructions. + +Definition get_valid_jump_destinations : M unit := + (* + 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. + *) + let* valid_jump_destinations := set (| + + |) in + let* pc := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..56ea324c84 --- /dev/null +++ b/coq/ethereum/constantinople/vm/stack.v @@ -0,0 +1,53 @@ +(* +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 constantinople.vm.exceptions. + +Definition pop : M unit := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + + +Definition push : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + 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..3cf9aab6e1 --- /dev/null +++ b/coq/ethereum/crypto/__init__.v @@ -0,0 +1,4 @@ +(* +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..3250649704 --- /dev/null +++ b/coq/ethereum/crypto/alt_bn128.v @@ -0,0 +1,77 @@ +(* +The alt_bn128 curve +^^^^^^^^^^^^^^^^^^^ +*) + + +Definition bnf2_to_bnf12 : M unit := + (* + Lift a field element in `BNF2` to `BNF12`. + *) + (* TODO statement *) + + +Definition bnp_to_bnp12 : M unit := + (* + Lift a point from `BNP` to `BNP12`. + *) + (* TODO statement *) + + +Definition twist : M unit := + (* + Apply to twist to change variables from the curve `BNP2` to `BNP12`. + *) + (* TODO statement *) + + +Definition linefunc : M unit := + (* + 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 *) + + +Definition miller_loop : M unit := + (* + The core of the pairing algorithm. + *) + (* TODO statement *) + let* r := q in + let* f := BNF12.["from_int"] (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* q1 := BNP12 (| + q.["x"].["frobenius"] (| + + |), + q.["y"].["frobenius"] (| + + |) + |) in + let* nq2 := BNP12 (| + q1.["x"].["frobenius"] (| + + |), + (* TODO expression *) + |) in + let* f := (* TODO expression *) in + let* r := (* TODO expression *) in + let* f := (* TODO expression *) in + (* TODO statement *) + + +Definition pairing : M unit := + (* + Compute the pairing of `q` and `p`. + *) + (* TODO statement *) + 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..19be3410de --- /dev/null +++ b/coq/ethereum/crypto/blake2.v @@ -0,0 +1,23 @@ +(* +The Blake2 Implementation +^^^^^^^^^^^^^^^^^^^^^^^^^^ +*) + + +Definition spit_le_to_uint : M unit := + (* + 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 + *) + let* words := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..8d2abcc5dd --- /dev/null +++ b/coq/ethereum/crypto/elliptic_curve.v @@ -0,0 +1,48 @@ +(* +Elliptic Curves +^^^^^^^^^^^^^^^ +*) + +Require typing. + +Definition secp256k1_recover : M unit := + (* + 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. + *) + let* r_bytes := r.["to_be_bytes32"] (| + + |) in + let* s_bytes := s.["to_be_bytes32"] (| + + |) in + let* signature := bytearray (| + (* TODO expression *) + |) in + (* TODO assignment *) + (* TODO assignment *) + (* TODO assignment *) + let* public_key := coincurve.["PublicKey"].["from_signature_and_message"] (| + bytes (| + signature + |), + msg_hash + |) in + let* public_key := (* TODO expression *) in + (* TODO statement *) + 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..4137029435 --- /dev/null +++ b/coq/ethereum/crypto/finite_field.v @@ -0,0 +1,8 @@ +(* +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..07b05e502d --- /dev/null +++ b/coq/ethereum/crypto/hash.v @@ -0,0 +1,56 @@ +(* +Cryptographic Hash Functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Cryptographic hashing functions. +*) + +Require Crypto.Hash. +Require ethereum_types.bytes. + +Definition keccak256 : M unit := + (* + 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. + *) + let* k := Crypto.Hash.keccak.["new"] (| + + |) in + (* TODO statement *) + + +Definition keccak512 : M unit := + (* + 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. + *) + let* k := Crypto.Hash.keccak.["new"] (| + + |) in + (* TODO statement *) + 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..f238af8287 --- /dev/null +++ b/coq/ethereum/crypto/kzg.v @@ -0,0 +1,129 @@ +(* +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 : M unit := + (* + Convert a KZG commitment to a versioned hash. + *) + (* TODO statement *) + + +Definition validate_kzg_g1 : M unit := + (* + Perform BLS validation required by the types `KZGProof` + and `KZGCommitment`. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_kzg_commitment : M unit := + (* + Convert untrusted bytes into a trusted and validated KZGCommitment. + *) + do* validate_kzg_g1 (| + b + |) in + (* TODO statement *) + + +Definition bytes_to_bls_field : M unit := + (* + Convert untrusted bytes to a trusted and validated BLS scalar + field element. This function does not accept inputs greater than + the BLS modulus. + *) + let* field_element := int.["from_bytes"] (| + b, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_kzg_proof : M unit := + (* + Convert untrusted bytes into a trusted and validated KZGProof. + *) + do* validate_kzg_g1 (| + b + |) in + (* TODO statement *) + + +Definition pairing_check : M unit := + (* + Check if the pairings are valid. + *) + (* TODO assignment *) + let* final_exponentiation := py_ecc.optimized_bls12_381.optimized_pairing.final_exponentiate (| + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition verify_kzg_proof : M unit := + (* + 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 *) + + +Definition verify_kzg_proof_impl : M unit := + (* + Verify KZG proof that ``p(z) == y`` where ``p(z)`` + is the polynomial represented by ``polynomial_kzg``. + *) + let* 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 (| + KZG_SETUP_G2_MONOMIAL_1 + |) + |) + |), + py_ecc.optimized_bls12_381.multiply (| + py_ecc.optimized_bls12_381.optimized_curve.G2, + int (| + (* TODO expression *) + |) + |) + |) in + let* 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, + int (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + 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..914a333705 --- /dev/null +++ b/coq/ethereum/dao_fork/__init__.v @@ -0,0 +1,7 @@ +(* +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..c5bce08268 --- /dev/null +++ b/coq/ethereum/dao_fork/blocks.v @@ -0,0 +1,19 @@ +(* +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 ..crypto.hash. +Require dao_fork.fork_types. +Require 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..eb4e32e729 --- /dev/null +++ b/coq/ethereum/dao_fork/bloom.v @@ -0,0 +1,66 @@ +(* +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 dao_fork.blocks. +Require dao_fork.fork_types. + +Definition add_to_bloom : 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. + *) + let* hash := ethereum.crypto.hash.keccak256 (| + bloom_entry + |) in + (* TODO statement *) + + +Definition logs_bloom : M unit := + (* + 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 *) + 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..bda8ac1af5 --- /dev/null +++ b/coq/ethereum/dao_fork/dao.v @@ -0,0 +1,31 @@ +(* +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 dao_fork.state. +Require dao_fork.utils.hexadecimal. + +Definition apply_dao : M unit := + (* + Apply the dao fork to the state. + + Parameters + ---------- + state : + State before applying the DAO Fork. + *) + (* TODO statement *) + 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..c48075ab28 --- /dev/null +++ b/coq/ethereum/dao_fork/fork.v @@ -0,0 +1,758 @@ +(* +.. _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 dao_fork.blocks. +Require dao_fork.bloom. +Require dao_fork.dao. +Require dao_fork.fork_types. +Require dao_fork.state. +Require dao_fork.transactions. +Require dao_fork.trie. +Require dao_fork.utils.message. +Require dao_fork.vm.interpreter. + +Definition apply_fork : M unit := + (* + 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 (| + old.["state"] + |) in + (* TODO statement *) + + +Definition get_last_256_block_hashes : M unit := + (* + 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. + *) + let* recent_blocks := (* TODO expression *) in + (* TODO statement *) + let* recent_block_hashes := (* TODO expression *) in + (* TODO statement *) + let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *).["header"] + |) + |) in + do* recent_block_hashes.["append"] (| + most_recent_block_hash + |) in + (* TODO statement *) + + +Definition state_transition : 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`. + *) + let* parent_header := (* TODO expression *).["header"] in + do* validate_header (| + block.["header"], + parent_header + |) in + do* validate_ommers (| + block.["ommers"], + block.["header"], + chain + |) in + let* apply_body_output := apply_body (| + chain.["state"], + get_last_256_block_hashes (| + chain + |), + block.["header"].["coinbase"], + block.["header"].["number"], + block.["header"].["gas_limit"], + block.["header"].["timestamp"], + block.["header"].["difficulty"], + block.["transactions"], + block.["ommers"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* chain.["blocks"].["append"] (| + block + |) in + (* TODO statement *) + + +Definition validate_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 *) + let* block_difficulty := calculate_block_difficulty (| + header.["number"], + header.["timestamp"], + parent_header.["timestamp"], + parent_header.["difficulty"] + |) in + (* TODO statement *) + let* block_parent_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + parent_header + |) + |) in + (* TODO statement *) + (* TODO statement *) + do* validate_proof_of_work (| + header + |) in + + +Definition generate_header_hash_for_pow : M unit := + (* + 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. + *) + let* header_data_without_pow_artefacts := (* TODO expression *) in + (* TODO statement *) + + +Definition validate_proof_of_work : 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. + *) + let* header_hash := generate_header_hash_for_pow (| + header + |) in + let* cache := ethereum.ethash.generate_cache (| + header.["number"] + |) in + (* TODO assignment *) + (* TODO statement *) + let* limit := (* TODO expression *) in + (* TODO statement *) + + +Definition check_transaction : M unit := + (* + 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 *) + let* sender_address := recover_sender (| + tx + |) in + (* TODO statement *) + + +Definition make_receipt : M unit := + (* + 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. + *) + let* receipt := blocks.Receipt (| + + |) in + (* TODO statement *) + + +Definition apply_body : M unit := + (* + 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. + *) + let* gas_available := block_gas_limit in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* pay_rewards (| + state, + block_number, + coinbase, + ommers + |) in + let* block_gas_used := (* TODO expression *) in + let* block_logs_bloom := bloom.logs_bloom (| + block_logs + |) in + (* TODO statement *) + + +Definition validate_ommers : 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. + *) + let* block_hash := rlp.["rlp_hash"] (| + block_header + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* ommers_hashes := (* TODO expression *) in + (* TODO statement *) + let* recent_canonical_blocks := (* TODO expression *) in + let* recent_canonical_block_hashes := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition pay_rewards : 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. + *) + let* ommer_count := ethereum_types.numeric.U256 (| + len (| + ommers + |) + |) in + let* miner_reward := (* TODO expression *) in + do* state.create_ether (| + state, + coinbase, + miner_reward + |) in + (* TODO statement *) + + +Definition process_transaction : M unit := + (* + 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 *) + let* sender := env.["origin"] in + let* sender_account := state.get_account (| + env.["state"], + sender + |) in + let* gas_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* gas := (* TODO expression *) in + do* state.increment_nonce (| + env.["state"], + sender + |) in + let* sender_balance_after_gas_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + ethereum_types.numeric.U256 (| + sender_balance_after_gas_fee + |) + |) in + let* message := utils.message.prepare_message (| + sender, + tx.["to"], + tx.["value"], + tx.["data"], + gas, + env + |) in + let* output := vm.interpreter.process_message_call (| + message, + env + |) in + let* gas_used := (* TODO expression *) in + let* gas_refund := min (| + (* TODO expression *), + ethereum_types.numeric.Uint (| + output.["refund_counter"] + |) + |) in + let* gas_refund_amount := (* TODO expression *) in + let* transaction_fee := (* TODO expression *) in + let* total_gas_used := (* TODO expression *) in + let* sender_balance_after_refund := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + sender_balance_after_refund + |) in + let* coinbase_balance_after_mining_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + env.["coinbase"], + coinbase_balance_after_mining_fee + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition validate_transaction : M unit := + (* + 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 *) + + +Definition calculate_intrinsic_cost : M unit := + (* + 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. + *) + let* data_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition recover_sender : M unit := + (* + 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 *) + let* public_key := ethereum.crypto.elliptic_curve.secp256k1_recover (| + r, + s, + (* TODO expression *), + signing_hash (| + tx + |) + |) in + (* TODO statement *) + + +Definition signing_hash : M unit := + (* + 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 *) + + +Definition compute_header_hash : M unit := + (* + 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 *) + + +Definition check_gas_limit : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_block_difficulty : M unit := + (* + 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. + *) + let* offset := (* TODO expression *) in + let* difficulty := (* TODO expression *) in + let* num_bomb_periods := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..14de99d5e5 --- /dev/null +++ b/coq/ethereum/dao_fork/fork_types.v @@ -0,0 +1,29 @@ +(* +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 ..crypto.hash. + +Definition encode_account : M unit := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + 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..fd32ea6e73 --- /dev/null +++ b/coq/ethereum/dao_fork/state.v @@ -0,0 +1,471 @@ +(* +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 dao_fork.fork_types. +Require dao_fork.trie. + +Definition close_state : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition begin_transaction : 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* state.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + + +Definition commit_transaction : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* state.["_snapshots"].["pop"] (| + + |) in + + +Definition rollback_transaction : 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 *) + + +Definition get_account : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition get_account_optional : M unit := + (* + 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. + *) + let* account := trie.trie_get (| + state.["_main_trie"], + address + |) in + (* TODO statement *) + + +Definition set_account : 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 (| + state.["_main_trie"], + address, + account + |) in + + +Definition destroy_account : 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* destroy_storage (| + state, + address + |) in + do* set_account (| + state, + address, + (* TODO expression *) + |) in + + +Definition destroy_storage : 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 *) + + +Definition get_storage : M unit := + (* + 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. + *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_storage : 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 *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition storage_root : M unit := + (* + 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 *) + + +Definition state_root : M unit := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition account_exists : M unit := + (* + 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 *) + + +Definition account_has_code_or_nonce : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition modify_state : M unit := + (* + Modify an `Account` in the `State`. + *) + do* set_account (| + state, + address, + ethereum_types.frozen.modify (| + get_account (| + state, + address + |), + f + |) + |) in + + +Definition move_ether : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* modify_state (| + state, + sender_address, + reduce_sender_balance + |) in + do* modify_state (| + state, + recipient_address, + increase_recipient_balance + |) in + + +Definition set_account_balance : 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* modify_state (| + state, + address, + set_balance + |) in + + +Definition touch_account : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + + +Definition increment_nonce : 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* modify_state (| + state, + address, + increase_nonce + |) in + + +Definition set_code : 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* modify_state (| + state, + address, + write_code + |) in + + +Definition create_ether : 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* modify_state (| + state, + address, + increase_balance + |) in + 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..499d5305a6 --- /dev/null +++ b/coq/ethereum/dao_fork/transactions.v @@ -0,0 +1,12 @@ +(* +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 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..548de91e1c --- /dev/null +++ b/coq/ethereum/dao_fork/trie.v @@ -0,0 +1,274 @@ +(* +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 : M unit := + (* + 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 *) + let* encoded := rlp.["encode"] (| + unencoded + |) in + (* TODO statement *) + + +Definition encode_node : M unit := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + + +Definition copy_trie : M unit := + (* + 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 *) + + +Definition trie_set : 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 *) + + +Definition trie_get : M unit := + (* + 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 *) + + +Definition common_prefix_length : M unit := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition nibble_list_to_compact : M unit := + (* + 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. + *) + let* compact := bytearray (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_nibble_list : M unit := + (* + 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. + *) + let* nibble_list := bytearray (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _prepare_trie : M unit := + (* + 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 *) + + +Definition root : M unit := + (* + 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. + *) + let* obj := _prepare_trie (| + trie, + get_storage_root + |) in + let* root_node := encode_internal_node (| + patricialize (| + obj, + Uint (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + + +Definition patricialize : M unit := + (* + 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 *) + let* arbitrary_key := next (| + iter (| + obj + |) + |) in + (* TODO statement *) + let* substring := (* TODO expression *) in + let* prefix_length := len (| + substring + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..beff4482b1 --- /dev/null +++ b/coq/ethereum/dao_fork/utils/__init__.v @@ -0,0 +1,4 @@ +(* +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..1a0612f347 --- /dev/null +++ b/coq/ethereum/dao_fork/utils/address.v @@ -0,0 +1,66 @@ +(* +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 dao_fork.fork_types. + +Definition to_address : M unit := + (* + 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 *) + + +Definition compute_contract_address : M unit := + (* + 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. + *) + let* computed_address := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *) + |) + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + 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..3d24a9bec3 --- /dev/null +++ b/coq/ethereum/dao_fork/utils/hexadecimal.v @@ -0,0 +1,68 @@ +(* +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 dao_fork.fork_types. + +Definition hex_to_root : M unit := + (* + 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 *) + + +Definition hex_to_bloom : M unit := + (* + 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 *) + + +Definition hex_to_address : M unit := + (* + 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 *) + 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..aab7d018ff --- /dev/null +++ b/coq/ethereum/dao_fork/utils/message.v @@ -0,0 +1,55 @@ +(* +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 dao_fork.fork_types. +Require dao_fork.state. +Require dao_fork.vm. +Require dao_fork.utils.address. + +Definition prepare_message : M unit := + (* + 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 *) + 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..52d657c646 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/__init__.v @@ -0,0 +1,56 @@ +(* +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 dao_fork.blocks. +Require dao_fork.fork_types. +Require dao_fork.state. + +Definition incorporate_child_on_success : 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* evm.["accounts_to_delete"].["update"] (| + child_evm.["accounts_to_delete"] + |) in + + +Definition incorporate_child_on_error : 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 *) + 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..1784494410 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/exceptions.v @@ -0,0 +1,15 @@ +(* +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..0bad5a417e --- /dev/null +++ b/coq/ethereum/dao_fork/vm/gas.v @@ -0,0 +1,125 @@ +(* +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 dao_fork.fork_types. +Require dao_fork.state. +Require dao_fork.vm.exceptions. + +Definition charge_gas : 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 (| + int (| + amount + |) + |) + |) in + (* TODO statement *) + + +Definition calculate_memory_gas_cost : M unit := + (* + 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. + *) + let* size_in_words := (* TODO expression *) in + let* linear_cost := (* TODO expression *) in + let* quadratic_cost := (* TODO expression *) in + let* total_gas_cost := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_gas_extend_memory : M unit := + (* + 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` + *) + let* size_to_extend := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* to_be_paid := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* current_size := ethereum_types.numeric.Uint (| + len (| + memory + |) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_message_call_gas : M unit := + (* + 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` + *) + let* create_gas_cost := (* TODO expression *) in + let* transfer_gas_cost := (* TODO expression *) in + let* cost := (* TODO expression *) in + let* stipend := (* TODO expression *) in + (* TODO statement *) + 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..b36b1ebfef --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/__init__.v @@ -0,0 +1,15 @@ +(* +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..4a435c46f1 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/arithmetic.v @@ -0,0 +1,387 @@ +(* +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 dao_fork.vm.gas. +Require dao_fork.vm.stack. + +Definition add : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_add"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition sub : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_sub"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mul : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + let* result := x.["wrapping_mul"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition div : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |) in + let* divisor := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + quotient + |) in + (* TODO statement *) + + +Definition sdiv : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* divisor := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + quotient + |) + |) in + (* TODO statement *) + + +Definition mod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + remainder + |) in + (* TODO statement *) + + +Definition smod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* y := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + remainder + |) + |) in + (* TODO statement *) + + +Definition addmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mulmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition exp : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* base := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent_bits := exponent.["bit_length"] (| + + |) in + let* exponent_bytes := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* result := ethereum_types.numeric.U256 (| + pow (| + base, + exponent, + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signextend : 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. + + *) + let* byte_num := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..682682eb38 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/bitwise.v @@ -0,0 +1,156 @@ +(* +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 dao_fork.vm.gas. +Require dao_fork.vm.stack. + +Definition bitwise_and : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_or : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_xor : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_not : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition get_byte : 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. + + *) + let* byte_index := stack.pop (| + evm.["stack"] + |) in + let* word := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..06298223b7 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/block.v @@ -0,0 +1,183 @@ +(* +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 dao_fork.vm.gas. +Require dao_fork.vm.stack. + +Definition block_hash : 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. + + *) + let* block_number := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOCK_HASH + |) in + let* max_block_number := (* TODO expression *) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + + +Definition coinbase : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["coinbase"] + |) + |) in + (* TODO statement *) + + +Definition timestamp : 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 (| + evm.["stack"], + evm.["env"].["time"] + |) in + (* TODO statement *) + + +Definition number : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["number"] + |) + |) in + (* TODO statement *) + + +Definition difficulty : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["difficulty"] + |) + |) in + (* TODO statement *) + + +Definition gas_limit : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_limit"] + |) + |) in + (* TODO statement *) + 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..1cf3a9aebd --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/comparison.v @@ -0,0 +1,206 @@ +(* +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 dao_fork.vm.gas. +Require dao_fork.vm.stack. + +Definition less_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_less_than : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition greater_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_greater_than : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition equal : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition is_zero : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..3cb1d463cf --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/control_flow.v @@ -0,0 +1,156 @@ +(* +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 dao_fork.vm.gas. +Require dao_fork.vm.exceptions. +Require dao_fork.vm.stack. + +Definition stop : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition jump : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_MID + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition jumpi : 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. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* conditional_value := stack.pop (| + evm.["stack"] + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_HIGH + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition pc : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["pc"] + |) + |) in + (* TODO statement *) + + +Definition gas_left : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + + +Definition jumpdest : 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 *) + (* TODO statement *) + 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..0e0a714f5b --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/environment.v @@ -0,0 +1,434 @@ +(* +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 dao_fork.state. +Require dao_fork.utils.address. +Require dao_fork.vm.memory. +Require dao_fork.vm.gas. +Require dao_fork.vm.stack. + +Definition address : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["current_target"] + |) + |) in + (* TODO statement *) + + +Definition balance : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BALANCE + |) in + let* balance := state.get_account (| + evm.["env"].["state"], + address + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition origin : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["origin"] + |) + |) in + (* TODO statement *) + + +Definition caller : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["caller"] + |) + |) in + (* TODO statement *) + + +Definition callvalue : 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 (| + evm.["stack"], + evm.["message"].["value"] + |) in + (* TODO statement *) + + +Definition calldataload : 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. + + *) + let* start_index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + start_index, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + value + |) + |) in + (* TODO statement *) + + +Definition calldatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["message"].["data"] + |) + |) + |) in + (* TODO statement *) + + +Definition calldatacopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* data_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + data_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition codesize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["code"] + |) + |) + |) in + (* TODO statement *) + + +Definition codecopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["code"], + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition gasprice : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_price"] + |) + |) in + (* TODO statement *) + + +Definition extcodesize : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_EXTERNAL + |) in + let* codesize := ethereum_types.numeric.U256 (| + len (| + state.get_account (| + evm.["env"].["state"], + address + |).["code"] + |) + |) in + do* stack.push (| + evm.["stack"], + codesize + |) in + (* TODO statement *) + + +Definition extcodecopy : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* code := state.get_account (| + evm.["env"].["state"], + address + |).["code"] in + let* value := vm.memory.buffer_read (| + code, + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + 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..21a120efc3 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/keccak.v @@ -0,0 +1,67 @@ +(* +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 dao_fork.vm.gas. +Require dao_fork.vm.memory. +Require dao_fork.vm.stack. + +Definition keccak : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* word_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + let* hash := ethereum.crypto.hash.keccak256 (| + data + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + 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..8e37508fa5 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/log.v @@ -0,0 +1,59 @@ +(* +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 dao_fork.blocks. +Require dao_fork.vm.gas. +Require dao_fork.vm.memory. +Require dao_fork.vm.stack. + +Definition log_n : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* topics := (* TODO expression *) in + (* TODO statement *) + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* log_entry := blocks.Log (| + + |) in + (* TODO assignment *) + (* TODO statement *) + 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..20cbc79690 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/memory.v @@ -0,0 +1,158 @@ +(* +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 dao_fork.vm.gas. +Require dao_fork.vm.memory. +Require dao_fork.vm.stack. + +Definition mstore : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* memory.memory_write (| + evm.["memory"], + start_position, + value + |) in + (* TODO statement *) + + +Definition mstore8 : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + (* TODO expression *) + |) in + do* memory.memory_write (| + evm.["memory"], + start_position, + normalized_bytes_value + |) in + (* TODO statement *) + + +Definition mload : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.memory_read_bytes (| + evm.["memory"], + start_position, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition msize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["memory"] + |) + |) + |) in + (* TODO statement *) + 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..5142bf11c3 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/stack.v @@ -0,0 +1,133 @@ +(* +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 dao_fork.vm.exceptions. +Require dao_fork.vm.gas. +Require dao_fork.vm.memory. + +Definition pop : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* stack.["pop"] (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BASE + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition push_n : 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 + let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + evm.["code"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + num_bytes + |) + |) + |) in + do* stack.["push"] (| + evm.["stack"], + data_to_push + |) in + (* TODO statement *) + + +Definition dup_n : 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 *) + let* data_to_duplicate := (* TODO expression *) in + do* stack.["push"] (| + evm.["stack"], + data_to_duplicate + |) in + (* TODO statement *) + + +Definition swap_n : 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 *) + (* TODO statement *) + 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..4bec3f185c --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/storage.v @@ -0,0 +1,88 @@ +(* +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 dao_fork.state. +Require dao_fork.vm.gas. +Require dao_fork.vm.stack. + +Definition sload : 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. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_SLOAD + |) in + let* value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition sstore : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + let* current_value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + do* state.set_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + 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..3639a4aa26 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/system.v @@ -0,0 +1,357 @@ +(* +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 dao_fork.fork_types. +Require dao_fork.state. +Require dao_fork.utils.address. +Require dao_fork.vm.gas. +Require dao_fork.vm.memory. +Require dao_fork.vm.stack. + +Definition create : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* create_message_gas := evm.["gas_left"] in + (* TODO assignment *) + (* TODO statement *) + let* sender_address := evm.["message"].["current_target"] in + let* sender := state.get_account (| + evm.["env"].["state"], + sender_address + |) in + let* contract_address := utils.address.compute_contract_address (| + evm.["message"].["current_target"], + state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["nonce"] + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition return_ : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + + +Definition generic_call : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_input_start_position, + memory_input_size + |) in + let* code := state.get_account (| + evm.["env"].["state"], + code_address + |).["code"] in + let* child_message := Message (| + + |) in + let* child_evm := process_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + let* actual_output_size := min (| + memory_output_size, + ethereum_types.numeric.U256 (| + len (| + child_evm.["output"] + |) + |) + |) in + do* memory.memory_write (| + evm.["memory"], + memory_output_start_position, + (* TODO expression *) + |) in + + +Definition call : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* message_call_gas := gas.calculate_message_call_gas (| + evm.["env"].["state"], + gas, + to, + value + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition callcode : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* to := evm.["message"].["current_target"] in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* message_call_gas := gas.calculate_message_call_gas (| + evm.["env"].["state"], + gas, + to, + value + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition selfdestruct : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* beneficiary := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* gas_cost := gas.GAS_ZERO in + let* originator := evm.["message"].["current_target"] in + let* refunded_accounts := evm.["accounts_to_delete"] in + let* parent_evm := evm.["message"].["parent_evm"] in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + let* beneficiary_balance := state.get_account (| + evm.["env"].["state"], + beneficiary + |).["balance"] in + let* originator_balance := state.get_account (| + evm.["env"].["state"], + originator + |).["balance"] in + do* state.set_account_balance (| + evm.["env"].["state"], + beneficiary, + (* TODO expression *) + |) in + do* state.set_account_balance (| + evm.["env"].["state"], + originator, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* evm.["accounts_to_delete"].["add"] (| + originator + |) in + (* TODO assignment *) + (* TODO statement *) + + +Definition delegatecall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + gas, + evm.["message"].["value"], + evm.["message"].["caller"], + evm.["message"].["current_target"], + code_address, + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + 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..944cae5883 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/interpreter.v @@ -0,0 +1,151 @@ +(* +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 dao_fork.blocks. +Require dao_fork.fork_types. +Require dao_fork.state. +Require dao_fork.vm. +Require dao_fork.vm.gas. +Require dao_fork.vm.precompiled_contracts.mapping. +Require dao_fork.vm.exceptions. +Require dao_fork.vm.instructions. +Require dao_fork.vm.runtime. + +Definition process_message_call : M unit := + (* + 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 *) + let* tx_end := ethereum.trace.TransactionEnd (| + (* TODO expression *), + evm.["output"], + evm.["error"] + |) in + do* ethereum.trace.evm_trace (| + evm, + tx_end + |) in + (* TODO statement *) + + +Definition process_create_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.destroy_storage (| + env.["state"], + message.["current_target"] + |) in + let* evm := process_message (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.touch_account (| + env.["state"], + message.["current_target"] + |) in + (* TODO statement *) + let* evm := execute_code (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition execute_code : M unit := + (* + 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 + *) + let* code := message.["code"] in + let* valid_jump_destinations := runtime.get_valid_jump_destinations (| + code + |) in + let* evm := Evm (| + + |) in + (* TODO statement *) + (* TODO statement *) + 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..94b6a44639 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/memory.v @@ -0,0 +1,75 @@ +(* +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 : 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 *) + + +Definition memory_read_bytes : M unit := + (* + 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 *) + + +Definition buffer_read : M unit := + (* + 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 *) + 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..1b69820379 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/__init__.v @@ -0,0 +1,16 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require 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..13c3dec3b8 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,93 @@ +(* +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 dao_fork.vm. +Require dao_fork.vm.gas. +Require dao_fork.vm.memory. + +Definition ecrecover : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_ECRECOVER + |) in + let* message_hash_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* message_hash := ethereum.crypto.hash.Hash32 (| + message_hash_bytes + |) in + let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + address, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..4a985124fa --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/identity.v @@ -0,0 +1,36 @@ +(* +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 dao_fork.vm. +Require dao_fork.vm.gas. + +Definition identity : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..83c8947d22 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/mapping.v @@ -0,0 +1,20 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require dao_fork.fork_types. +Require dao_fork.vm.precompiled_contracts.ecrecover. +Require dao_fork.vm.precompiled_contracts.identity. +Require dao_fork.vm.precompiled_contracts.ripemd160. +Require 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..bc5e73dd3c --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,42 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + let* hash_bytes := hashlib.["new"] (| + (* TODO expression *), + data + |).["digest"] (| + + |) in + let* padded_hash := left_pad_zero_bytes (| + hash_bytes, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..da6972d411 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/sha256.v @@ -0,0 +1,32 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..ac92e20add --- /dev/null +++ b/coq/ethereum/dao_fork/vm/runtime.v @@ -0,0 +1,49 @@ +(* +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 dao_fork.vm.instructions. + +Definition get_valid_jump_destinations : M unit := + (* + 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. + *) + let* valid_jump_destinations := set (| + + |) in + let* pc := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..ba1052d24e --- /dev/null +++ b/coq/ethereum/dao_fork/vm/stack.v @@ -0,0 +1,53 @@ +(* +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 dao_fork.vm.exceptions. + +Definition pop : M unit := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + + +Definition push : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + 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..cd1be88eed --- /dev/null +++ b/coq/ethereum/ethash.v @@ -0,0 +1,287 @@ +(* +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 : M unit := + (* + 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 *) + + +Definition cache_size : M unit := + (* + 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 + *) + let* size := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition dataset_size : M unit := + (* + 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 + *) + let* size := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition generate_seed : M unit := + (* + Obtain the cache generation seed for the block identified by + `block_number`. See [`generate_cache`]. + + [`generate_cache`]: ref:ethereum.ethash.generate_cache + *) + let* epoch_number := epoch (| + block_number + |) in + let* seed := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + + +Definition generate_cache : M unit := + (* + 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 + *) + let* seed := generate_seed (| + block_number + |) in + let* cache_size_bytes := cache_size (| + block_number + |) in + let* cache_size_words := (* TODO expression *) in + let* cache := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition fnv : M unit := + (* + 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 + *) + let* result := (* TODO expression *) in + (* TODO statement *) + + +Definition fnv_hash : M unit := + (* + 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 *) + + +Definition generate_dataset_item : M unit := + (* + 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 + *) + let* mix := ethereum.crypto.hash.keccak512 (| + (* TODO expression *).["to_le_bytes64"] (| + + |) + |) in + let* mix_integers := ethereum.utils.numeric.le_bytes_to_uint32_sequence (| + mix + |) in + (* TODO statement *) + let* mix := ethereum.crypto.hash.Hash64 (| + ethereum.utils.numeric.le_uint32_sequence_to_bytes (| + mix_integers + |) + |) in + (* TODO statement *) + + +Definition generate_dataset : M unit := + (* + 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 *) + + +Definition hashimoto : M unit := + (* + 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 + *) + let* nonce_le := bytes (| + reversed (| + nonce + |) + |) in + let* seed_hash := ethereum.crypto.hash.keccak512 (| + (* TODO expression *) + |) in + let* seed_head := ethereum_types.numeric.U32.["from_le_bytes"] (| + (* TODO expression *) + |) in + let* rows := (* TODO expression *) in + let* mix := (* TODO expression *) in + (* TODO statement *) + let* compressed_mix := (* TODO expression *) in + (* TODO statement *) + let* mix_digest := ethereum.utils.numeric.le_uint32_sequence_to_bytes (| + compressed_mix + |) in + let* result := ethereum.crypto.hash.keccak256 (| + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition hashimoto_light : M unit := + (* + 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 *) + 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..ff2a9d09cd --- /dev/null +++ b/coq/ethereum/exceptions.v @@ -0,0 +1,4 @@ +(* +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..6e2fcf37f3 --- /dev/null +++ b/coq/ethereum/fork_criteria.v @@ -0,0 +1,26 @@ +(* +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..68355e6ddd --- /dev/null +++ b/coq/ethereum/frontier/__init__.v @@ -0,0 +1,5 @@ +(* +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..0a4788712a --- /dev/null +++ b/coq/ethereum/frontier/blocks.v @@ -0,0 +1,19 @@ +(* +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 ..crypto.hash. +Require frontier.fork_types. +Require 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..82669c6c5e --- /dev/null +++ b/coq/ethereum/frontier/bloom.v @@ -0,0 +1,66 @@ +(* +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 frontier.blocks. +Require frontier.fork_types. + +Definition add_to_bloom : 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. + *) + let* hash := ethereum.crypto.hash.keccak256 (| + bloom_entry + |) in + (* TODO statement *) + + +Definition logs_bloom : M unit := + (* + 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 *) + 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..c8fcbddea6 --- /dev/null +++ b/coq/ethereum/frontier/fork.v @@ -0,0 +1,736 @@ +(* +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 frontier.blocks. +Require frontier.bloom. +Require frontier.fork_types. +Require frontier.state. +Require frontier.transactions. +Require frontier.trie. +Require frontier.utils.message. +Require frontier.vm.interpreter. + +Definition apply_fork : M unit := + (* + 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 *) + + +Definition get_last_256_block_hashes : M unit := + (* + 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. + *) + let* recent_blocks := (* TODO expression *) in + (* TODO statement *) + let* recent_block_hashes := (* TODO expression *) in + (* TODO statement *) + let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *).["header"] + |) + |) in + do* recent_block_hashes.["append"] (| + most_recent_block_hash + |) in + (* TODO statement *) + + +Definition state_transition : 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`. + *) + let* parent_header := (* TODO expression *).["header"] in + do* validate_header (| + block.["header"], + parent_header + |) in + do* validate_ommers (| + block.["ommers"], + block.["header"], + chain + |) in + let* apply_body_output := apply_body (| + chain.["state"], + get_last_256_block_hashes (| + chain + |), + block.["header"].["coinbase"], + block.["header"].["number"], + block.["header"].["gas_limit"], + block.["header"].["timestamp"], + block.["header"].["difficulty"], + block.["transactions"], + block.["ommers"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* chain.["blocks"].["append"] (| + block + |) in + (* TODO statement *) + + +Definition validate_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 *) + let* block_difficulty := calculate_block_difficulty (| + header.["number"], + header.["timestamp"], + parent_header.["timestamp"], + parent_header.["difficulty"] + |) in + (* TODO statement *) + let* block_parent_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + parent_header + |) + |) in + (* TODO statement *) + do* validate_proof_of_work (| + header + |) in + + +Definition generate_header_hash_for_pow : M unit := + (* + 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. + *) + let* header_data_without_pow_artefacts := (* TODO expression *) in + (* TODO statement *) + + +Definition validate_proof_of_work : 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. + *) + let* header_hash := generate_header_hash_for_pow (| + header + |) in + let* cache := ethereum.ethash.generate_cache (| + header.["number"] + |) in + (* TODO assignment *) + (* TODO statement *) + let* limit := (* TODO expression *) in + (* TODO statement *) + + +Definition check_transaction : M unit := + (* + 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 *) + let* sender_address := recover_sender (| + tx + |) in + (* TODO statement *) + + +Definition make_receipt : M unit := + (* + 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. + *) + let* receipt := blocks.Receipt (| + + |) in + (* TODO statement *) + + +Definition apply_body : M unit := + (* + 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. + *) + let* gas_available := block_gas_limit in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* pay_rewards (| + state, + block_number, + coinbase, + ommers + |) in + let* block_gas_used := (* TODO expression *) in + let* block_logs_bloom := bloom.logs_bloom (| + block_logs + |) in + (* TODO statement *) + + +Definition validate_ommers : 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. + *) + let* block_hash := rlp.["rlp_hash"] (| + block_header + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* ommers_hashes := (* TODO expression *) in + (* TODO statement *) + let* recent_canonical_blocks := (* TODO expression *) in + let* recent_canonical_block_hashes := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition pay_rewards : 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. + *) + let* ommer_count := ethereum_types.numeric.U256 (| + len (| + ommers + |) + |) in + let* miner_reward := (* TODO expression *) in + do* state.create_ether (| + state, + coinbase, + miner_reward + |) in + (* TODO statement *) + + +Definition process_transaction : M unit := + (* + 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 *) + let* sender := env.["origin"] in + let* sender_account := state.get_account (| + env.["state"], + sender + |) in + let* gas_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* gas := (* TODO expression *) in + do* state.increment_nonce (| + env.["state"], + sender + |) in + let* sender_balance_after_gas_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + ethereum_types.numeric.U256 (| + sender_balance_after_gas_fee + |) + |) in + let* message := utils.message.prepare_message (| + sender, + tx.["to"], + tx.["value"], + tx.["data"], + gas, + env + |) in + let* output := vm.interpreter.process_message_call (| + message, + env + |) in + let* gas_used := (* TODO expression *) in + let* gas_refund := min (| + (* TODO expression *), + ethereum_types.numeric.Uint (| + output.["refund_counter"] + |) + |) in + let* gas_refund_amount := (* TODO expression *) in + let* transaction_fee := (* TODO expression *) in + let* total_gas_used := (* TODO expression *) in + let* sender_balance_after_refund := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + sender_balance_after_refund + |) in + let* coinbase_balance_after_mining_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + env.["coinbase"], + coinbase_balance_after_mining_fee + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition validate_transaction : M unit := + (* + 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 *) + + +Definition calculate_intrinsic_cost : M unit := + (* + 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. + *) + let* data_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + + +Definition recover_sender : M unit := + (* + 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 *) + let* public_key := ethereum.crypto.elliptic_curve.secp256k1_recover (| + r, + s, + (* TODO expression *), + signing_hash (| + tx + |) + |) in + (* TODO statement *) + + +Definition signing_hash : M unit := + (* + 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 *) + + +Definition compute_header_hash : M unit := + (* + 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 *) + + +Definition check_gas_limit : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_block_difficulty : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + let* num_bomb_periods := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..14de99d5e5 --- /dev/null +++ b/coq/ethereum/frontier/fork_types.v @@ -0,0 +1,29 @@ +(* +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 ..crypto.hash. + +Definition encode_account : M unit := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + 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..bc6d2698de --- /dev/null +++ b/coq/ethereum/frontier/state.v @@ -0,0 +1,471 @@ +(* +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 frontier.fork_types. +Require frontier.trie. + +Definition close_state : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition begin_transaction : 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* state.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + + +Definition commit_transaction : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* state.["_snapshots"].["pop"] (| + + |) in + + +Definition rollback_transaction : 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 *) + + +Definition get_account : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition get_account_optional : M unit := + (* + 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. + *) + let* account := trie.trie_get (| + state.["_main_trie"], + address + |) in + (* TODO statement *) + + +Definition set_account : 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 (| + state.["_main_trie"], + address, + account + |) in + + +Definition destroy_account : 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* destroy_storage (| + state, + address + |) in + do* set_account (| + state, + address, + (* TODO expression *) + |) in + + +Definition destroy_storage : 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 *) + + +Definition get_storage : M unit := + (* + 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. + *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_storage : 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 *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition storage_root : M unit := + (* + 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 *) + + +Definition state_root : M unit := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition account_exists : M unit := + (* + 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 *) + + +Definition account_has_code_or_nonce : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition modify_state : M unit := + (* + Modify an `Account` in the `State`. + *) + do* set_account (| + state, + address, + ethereum_types.frozen.modify (| + get_account (| + state, + address + |), + f + |) + |) in + + +Definition move_ether : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* modify_state (| + state, + sender_address, + reduce_sender_balance + |) in + do* modify_state (| + state, + recipient_address, + increase_recipient_balance + |) in + + +Definition set_account_balance : 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* modify_state (| + state, + address, + set_balance + |) in + + +Definition touch_account : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + + +Definition increment_nonce : 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* modify_state (| + state, + address, + increase_nonce + |) in + + +Definition set_code : 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* modify_state (| + state, + address, + write_code + |) in + + +Definition create_ether : 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* modify_state (| + state, + address, + increase_balance + |) in + 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..42ba7f2ca3 --- /dev/null +++ b/coq/ethereum/frontier/transactions.v @@ -0,0 +1,12 @@ +(* +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 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..548de91e1c --- /dev/null +++ b/coq/ethereum/frontier/trie.v @@ -0,0 +1,274 @@ +(* +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 : M unit := + (* + 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 *) + let* encoded := rlp.["encode"] (| + unencoded + |) in + (* TODO statement *) + + +Definition encode_node : M unit := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + + +Definition copy_trie : M unit := + (* + 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 *) + + +Definition trie_set : 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 *) + + +Definition trie_get : M unit := + (* + 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 *) + + +Definition common_prefix_length : M unit := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition nibble_list_to_compact : M unit := + (* + 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. + *) + let* compact := bytearray (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_nibble_list : M unit := + (* + 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. + *) + let* nibble_list := bytearray (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _prepare_trie : M unit := + (* + 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 *) + + +Definition root : M unit := + (* + 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. + *) + let* obj := _prepare_trie (| + trie, + get_storage_root + |) in + let* root_node := encode_internal_node (| + patricialize (| + obj, + Uint (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + + +Definition patricialize : M unit := + (* + 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 *) + let* arbitrary_key := next (| + iter (| + obj + |) + |) in + (* TODO statement *) + let* substring := (* TODO expression *) in + let* prefix_length := len (| + substring + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..beff4482b1 --- /dev/null +++ b/coq/ethereum/frontier/utils/__init__.v @@ -0,0 +1,4 @@ +(* +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..76588f62aa --- /dev/null +++ b/coq/ethereum/frontier/utils/address.v @@ -0,0 +1,66 @@ +(* +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 frontier.fork_types. + +Definition to_address : M unit := + (* + 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 *) + + +Definition compute_contract_address : M unit := + (* + 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. + *) + let* computed_address := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *) + |) + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + 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..6915da1c3a --- /dev/null +++ b/coq/ethereum/frontier/utils/hexadecimal.v @@ -0,0 +1,68 @@ +(* +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 frontier.fork_types. + +Definition hex_to_root : M unit := + (* + 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 *) + + +Definition hex_to_bloom : M unit := + (* + 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 *) + + +Definition hex_to_address : M unit := + (* + 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 *) + 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..5a5df9c686 --- /dev/null +++ b/coq/ethereum/frontier/utils/message.v @@ -0,0 +1,53 @@ +(* +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 frontier.fork_types. +Require frontier.state. +Require frontier.vm. +Require frontier.utils.address. + +Definition prepare_message : M unit := + (* + 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 *) + 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..10896c0c78 --- /dev/null +++ b/coq/ethereum/frontier/vm/__init__.v @@ -0,0 +1,56 @@ +(* +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 frontier.blocks. +Require frontier.fork_types. +Require frontier.state. + +Definition incorporate_child_on_success : 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* evm.["accounts_to_delete"].["update"] (| + child_evm.["accounts_to_delete"] + |) in + + +Definition incorporate_child_on_error : 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 *) + 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..1784494410 --- /dev/null +++ b/coq/ethereum/frontier/vm/exceptions.v @@ -0,0 +1,15 @@ +(* +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..acf1e37bda --- /dev/null +++ b/coq/ethereum/frontier/vm/gas.v @@ -0,0 +1,125 @@ +(* +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 frontier.fork_types. +Require frontier.state. +Require frontier.vm.exceptions. + +Definition charge_gas : 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 (| + int (| + amount + |) + |) + |) in + (* TODO statement *) + + +Definition calculate_memory_gas_cost : M unit := + (* + 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. + *) + let* size_in_words := (* TODO expression *) in + let* linear_cost := (* TODO expression *) in + let* quadratic_cost := (* TODO expression *) in + let* total_gas_cost := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_gas_extend_memory : M unit := + (* + 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` + *) + let* size_to_extend := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* to_be_paid := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* current_size := ethereum_types.numeric.Uint (| + len (| + memory + |) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_message_call_gas : M unit := + (* + 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` + *) + let* create_gas_cost := (* TODO expression *) in + let* transfer_gas_cost := (* TODO expression *) in + let* cost := (* TODO expression *) in + let* stipend := (* TODO expression *) in + (* TODO statement *) + 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..b36b1ebfef --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/__init__.v @@ -0,0 +1,15 @@ +(* +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..b606a22e90 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/arithmetic.v @@ -0,0 +1,387 @@ +(* +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 frontier.vm.gas. +Require frontier.vm.stack. + +Definition add : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_add"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition sub : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_sub"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mul : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + let* result := x.["wrapping_mul"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition div : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |) in + let* divisor := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + quotient + |) in + (* TODO statement *) + + +Definition sdiv : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* divisor := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + quotient + |) + |) in + (* TODO statement *) + + +Definition mod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + remainder + |) in + (* TODO statement *) + + +Definition smod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* y := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + remainder + |) + |) in + (* TODO statement *) + + +Definition addmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mulmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition exp : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* base := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent_bits := exponent.["bit_length"] (| + + |) in + let* exponent_bytes := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* result := ethereum_types.numeric.U256 (| + pow (| + base, + exponent, + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signextend : 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. + + *) + let* byte_num := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..b4db7dd45a --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/bitwise.v @@ -0,0 +1,156 @@ +(* +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 frontier.vm.gas. +Require frontier.vm.stack. + +Definition bitwise_and : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_or : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_xor : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_not : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition get_byte : 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. + + *) + let* byte_index := stack.pop (| + evm.["stack"] + |) in + let* word := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..cb177ec3f1 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/block.v @@ -0,0 +1,183 @@ +(* +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 frontier.vm.gas. +Require frontier.vm.stack. + +Definition block_hash : 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. + + *) + let* block_number := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOCK_HASH + |) in + let* max_block_number := (* TODO expression *) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + + +Definition coinbase : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["coinbase"] + |) + |) in + (* TODO statement *) + + +Definition timestamp : 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 (| + evm.["stack"], + evm.["env"].["time"] + |) in + (* TODO statement *) + + +Definition number : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["number"] + |) + |) in + (* TODO statement *) + + +Definition difficulty : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["difficulty"] + |) + |) in + (* TODO statement *) + + +Definition gas_limit : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_limit"] + |) + |) in + (* TODO statement *) + 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..b2ab7fc92a --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/comparison.v @@ -0,0 +1,206 @@ +(* +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 frontier.vm.gas. +Require frontier.vm.stack. + +Definition less_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_less_than : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition greater_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_greater_than : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition equal : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition is_zero : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..1576250b1d --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/control_flow.v @@ -0,0 +1,156 @@ +(* +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 frontier.vm.gas. +Require frontier.vm.exceptions. +Require frontier.vm.stack. + +Definition stop : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition jump : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_MID + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition jumpi : 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. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* conditional_value := stack.pop (| + evm.["stack"] + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_HIGH + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition pc : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["pc"] + |) + |) in + (* TODO statement *) + + +Definition gas_left : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + + +Definition jumpdest : 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 *) + (* TODO statement *) + 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..e5bf97904a --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/environment.v @@ -0,0 +1,434 @@ +(* +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 frontier.state. +Require frontier.utils.address. +Require frontier.vm.memory. +Require frontier.vm.gas. +Require frontier.vm.stack. + +Definition address : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["current_target"] + |) + |) in + (* TODO statement *) + + +Definition balance : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BALANCE + |) in + let* balance := state.get_account (| + evm.["env"].["state"], + address + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition origin : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["origin"] + |) + |) in + (* TODO statement *) + + +Definition caller : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["caller"] + |) + |) in + (* TODO statement *) + + +Definition callvalue : 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 (| + evm.["stack"], + evm.["message"].["value"] + |) in + (* TODO statement *) + + +Definition calldataload : 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. + + *) + let* start_index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + start_index, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + value + |) + |) in + (* TODO statement *) + + +Definition calldatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["message"].["data"] + |) + |) + |) in + (* TODO statement *) + + +Definition calldatacopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* data_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + data_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition codesize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["code"] + |) + |) + |) in + (* TODO statement *) + + +Definition codecopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["code"], + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition gasprice : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_price"] + |) + |) in + (* TODO statement *) + + +Definition extcodesize : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_EXTERNAL + |) in + let* codesize := ethereum_types.numeric.U256 (| + len (| + state.get_account (| + evm.["env"].["state"], + address + |).["code"] + |) + |) in + do* stack.push (| + evm.["stack"], + codesize + |) in + (* TODO statement *) + + +Definition extcodecopy : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* code := state.get_account (| + evm.["env"].["state"], + address + |).["code"] in + let* value := vm.memory.buffer_read (| + code, + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + 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..e67dbb5979 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/keccak.v @@ -0,0 +1,67 @@ +(* +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 frontier.vm.gas. +Require frontier.vm.memory. +Require frontier.vm.stack. + +Definition keccak : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* word_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + let* hash := ethereum.crypto.hash.keccak256 (| + data + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + 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..4d9c4d0aef --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/log.v @@ -0,0 +1,59 @@ +(* +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 frontier.blocks. +Require frontier.vm.gas. +Require frontier.vm.memory. +Require frontier.vm.stack. + +Definition log_n : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* topics := (* TODO expression *) in + (* TODO statement *) + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* log_entry := blocks.Log (| + + |) in + (* TODO assignment *) + (* TODO statement *) + 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..7c58fb1ea5 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/memory.v @@ -0,0 +1,158 @@ +(* +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 frontier.vm.gas. +Require frontier.vm.memory. +Require frontier.vm.stack. + +Definition mstore : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* memory.memory_write (| + evm.["memory"], + start_position, + value + |) in + (* TODO statement *) + + +Definition mstore8 : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + (* TODO expression *) + |) in + do* memory.memory_write (| + evm.["memory"], + start_position, + normalized_bytes_value + |) in + (* TODO statement *) + + +Definition mload : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.memory_read_bytes (| + evm.["memory"], + start_position, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition msize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["memory"] + |) + |) + |) in + (* TODO statement *) + 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..b8ce6b4c9a --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/stack.v @@ -0,0 +1,133 @@ +(* +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 frontier.vm.exceptions. +Require frontier.vm.gas. +Require frontier.vm.memory. + +Definition pop : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* stack.["pop"] (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BASE + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition push_n : 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 + let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + evm.["code"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + num_bytes + |) + |) + |) in + do* stack.["push"] (| + evm.["stack"], + data_to_push + |) in + (* TODO statement *) + + +Definition dup_n : 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 *) + let* data_to_duplicate := (* TODO expression *) in + do* stack.["push"] (| + evm.["stack"], + data_to_duplicate + |) in + (* TODO statement *) + + +Definition swap_n : 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 *) + (* TODO statement *) + 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..111dc857a4 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/storage.v @@ -0,0 +1,88 @@ +(* +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 frontier.state. +Require frontier.vm.gas. +Require frontier.vm.stack. + +Definition sload : 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. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_SLOAD + |) in + let* value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition sstore : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + let* current_value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + do* state.set_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + 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..063c8888b8 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/system.v @@ -0,0 +1,301 @@ +(* +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 frontier.fork_types. +Require frontier.state. +Require frontier.utils.address. +Require frontier.vm.gas. +Require frontier.vm.memory. +Require frontier.vm.stack. + +Definition create : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* create_message_gas := evm.["gas_left"] in + (* TODO assignment *) + (* TODO statement *) + let* sender_address := evm.["message"].["current_target"] in + let* sender := state.get_account (| + evm.["env"].["state"], + sender_address + |) in + let* contract_address := utils.address.compute_contract_address (| + evm.["message"].["current_target"], + state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["nonce"] + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition return_ : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + + +Definition generic_call : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_input_start_position, + memory_input_size + |) in + let* code := state.get_account (| + evm.["env"].["state"], + code_address + |).["code"] in + let* child_message := Message (| + + |) in + let* child_evm := process_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + let* actual_output_size := min (| + memory_output_size, + ethereum_types.numeric.U256 (| + len (| + child_evm.["output"] + |) + |) + |) in + do* memory.memory_write (| + evm.["memory"], + memory_output_start_position, + (* TODO expression *) + |) in + + +Definition call : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* message_call_gas := gas.calculate_message_call_gas (| + evm.["env"].["state"], + gas, + to, + value + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition callcode : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* to := evm.["message"].["current_target"] in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* message_call_gas := gas.calculate_message_call_gas (| + evm.["env"].["state"], + gas, + to, + value + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition selfdestruct : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* beneficiary := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* gas_cost := gas.GAS_ZERO in + let* originator := evm.["message"].["current_target"] in + let* refunded_accounts := evm.["accounts_to_delete"] in + let* parent_evm := evm.["message"].["parent_evm"] in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + let* beneficiary_balance := state.get_account (| + evm.["env"].["state"], + beneficiary + |).["balance"] in + let* originator_balance := state.get_account (| + evm.["env"].["state"], + originator + |).["balance"] in + do* state.set_account_balance (| + evm.["env"].["state"], + beneficiary, + (* TODO expression *) + |) in + do* state.set_account_balance (| + evm.["env"].["state"], + originator, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* evm.["accounts_to_delete"].["add"] (| + originator + |) in + (* TODO assignment *) + (* TODO statement *) + 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..5cc08cb04f --- /dev/null +++ b/coq/ethereum/frontier/vm/interpreter.v @@ -0,0 +1,151 @@ +(* +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 frontier.blocks. +Require frontier.fork_types. +Require frontier.state. +Require frontier.vm. +Require frontier.vm.gas. +Require frontier.vm.precompiled_contracts.mapping. +Require frontier.vm.exceptions. +Require frontier.vm.instructions. +Require frontier.vm.runtime. + +Definition process_message_call : M unit := + (* + 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 *) + let* tx_end := ethereum.trace.TransactionEnd (| + (* TODO expression *), + evm.["output"], + evm.["error"] + |) in + do* ethereum.trace.evm_trace (| + evm, + tx_end + |) in + (* TODO statement *) + + +Definition process_create_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.destroy_storage (| + env.["state"], + message.["current_target"] + |) in + let* evm := process_message (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.touch_account (| + env.["state"], + message.["current_target"] + |) in + (* TODO statement *) + let* evm := execute_code (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition execute_code : M unit := + (* + 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 + *) + let* code := message.["code"] in + let* valid_jump_destinations := runtime.get_valid_jump_destinations (| + code + |) in + let* evm := Evm (| + + |) in + (* TODO statement *) + (* TODO statement *) + 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..94b6a44639 --- /dev/null +++ b/coq/ethereum/frontier/vm/memory.v @@ -0,0 +1,75 @@ +(* +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 : 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 *) + + +Definition memory_read_bytes : M unit := + (* + 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 *) + + +Definition buffer_read : M unit := + (* + 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 *) + 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..c38b032f9f --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/__init__.v @@ -0,0 +1,16 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require 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..818e3fd02c --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,93 @@ +(* +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 frontier.vm. +Require frontier.vm.gas. +Require frontier.vm.memory. + +Definition ecrecover : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_ECRECOVER + |) in + let* message_hash_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* message_hash := ethereum.crypto.hash.Hash32 (| + message_hash_bytes + |) in + let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + address, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..2707859a47 --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/identity.v @@ -0,0 +1,36 @@ +(* +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 frontier.vm. +Require frontier.vm.gas. + +Definition identity : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..b7c905d8d5 --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/mapping.v @@ -0,0 +1,20 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require frontier.fork_types. +Require frontier.vm.precompiled_contracts.ecrecover. +Require frontier.vm.precompiled_contracts.identity. +Require frontier.vm.precompiled_contracts.ripemd160. +Require 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..bc5e73dd3c --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,42 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + let* hash_bytes := hashlib.["new"] (| + (* TODO expression *), + data + |).["digest"] (| + + |) in + let* padded_hash := left_pad_zero_bytes (| + hash_bytes, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..da6972d411 --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/sha256.v @@ -0,0 +1,32 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..ea2f476cdf --- /dev/null +++ b/coq/ethereum/frontier/vm/runtime.v @@ -0,0 +1,49 @@ +(* +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 frontier.vm.instructions. + +Definition get_valid_jump_destinations : M unit := + (* + 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. + *) + let* valid_jump_destinations := set (| + + |) in + let* pc := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..ff1804132f --- /dev/null +++ b/coq/ethereum/frontier/vm/stack.v @@ -0,0 +1,53 @@ +(* +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 frontier.vm.exceptions. + +Definition pop : M unit := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + + +Definition push : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + 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..e7cc348c08 --- /dev/null +++ b/coq/ethereum/genesis.v @@ -0,0 +1,104 @@ +(* +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 : M unit := + (* + Read a genesis configuration from the given JSON file path. + + The genesis file should be present in the `assets` directory. + *) + let* genesis_path := (* TODO expression *) in + let* genesis_bytes := pkgutil.["get_data"] (| + (* TODO expression *), + genesis_path + |) in + (* TODO statement *) + let* genesis_data := json.["loads"] (| + genesis_bytes.["decode"] (| + + |) + |) in + (* TODO statement *) + + +Definition hex_or_base_10_str_to_u256 : M unit := + (* + Convert a string in either hexadecimal or base-10 to a `U256`. + *) + (* TODO statement *) + + +Definition add_genesis_block : 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 *) + let* fields := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* genesis_header := hardfork.["Header"] (| + + |) in + let* block_fields := (* TODO expression *) in + (* TODO statement *) + let* genesis_block := hardfork.["Block"] (| + + |) in + do* chain.["blocks"].["append"] (| + genesis_block + |) in + (* TODO assignment *) + 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..5e262a1a7b --- /dev/null +++ b/coq/ethereum/gray_glacier/__init__.v @@ -0,0 +1,6 @@ +(* +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..e159b28889 --- /dev/null +++ b/coq/ethereum/gray_glacier/blocks.v @@ -0,0 +1,19 @@ +(* +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 ..crypto.hash. +Require gray_glacier.fork_types. +Require 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..43fd209ef4 --- /dev/null +++ b/coq/ethereum/gray_glacier/bloom.v @@ -0,0 +1,66 @@ +(* +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 gray_glacier.blocks. +Require gray_glacier.fork_types. + +Definition add_to_bloom : 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. + *) + let* hash := ethereum.crypto.hash.keccak256 (| + bloom_entry + |) in + (* TODO statement *) + + +Definition logs_bloom : M unit := + (* + 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 *) + 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..137ea143f6 --- /dev/null +++ b/coq/ethereum/gray_glacier/exceptions.v @@ -0,0 +1,6 @@ +(* +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..3ce1f80cf7 --- /dev/null +++ b/coq/ethereum/gray_glacier/fork.v @@ -0,0 +1,847 @@ +(* +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 gray_glacier.blocks. +Require gray_glacier.bloom. +Require gray_glacier.fork_types. +Require gray_glacier.state. +Require gray_glacier.transactions. +Require gray_glacier.trie. +Require gray_glacier.utils.message. +Require gray_glacier.vm.interpreter. + +Definition apply_fork : M unit := + (* + 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 *) + + +Definition get_last_256_block_hashes : M unit := + (* + 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. + *) + let* recent_blocks := (* TODO expression *) in + (* TODO statement *) + let* recent_block_hashes := (* TODO expression *) in + (* TODO statement *) + let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *).["header"] + |) + |) in + do* recent_block_hashes.["append"] (| + most_recent_block_hash + |) in + (* TODO statement *) + + +Definition state_transition : 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`. + *) + let* parent_header := (* TODO expression *).["header"] in + do* validate_header (| + block.["header"], + parent_header + |) in + do* validate_ommers (| + block.["ommers"], + block.["header"], + chain + |) in + let* apply_body_output := apply_body (| + chain.["state"], + get_last_256_block_hashes (| + chain + |), + block.["header"].["coinbase"], + block.["header"].["number"], + block.["header"].["base_fee_per_gas"], + block.["header"].["gas_limit"], + block.["header"].["timestamp"], + block.["header"].["difficulty"], + block.["transactions"], + block.["ommers"], + chain.["chain_id"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* chain.["blocks"].["append"] (| + block + |) in + (* TODO statement *) + + +Definition calculate_base_fee_per_gas : M unit := + (* + 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. + *) + let* parent_gas_target := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_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 *) + let* expected_base_fee_per_gas := calculate_base_fee_per_gas (| + header.["gas_limit"], + parent_header.["gas_limit"], + parent_header.["gas_used"], + parent_header.["base_fee_per_gas"] + |) in + (* TODO statement *) + let* parent_has_ommers := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* block_difficulty := calculate_block_difficulty (| + header.["number"], + header.["timestamp"], + parent_header.["timestamp"], + parent_header.["difficulty"], + parent_has_ommers + |) in + (* TODO statement *) + let* block_parent_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + parent_header + |) + |) in + (* TODO statement *) + do* validate_proof_of_work (| + header + |) in + + +Definition generate_header_hash_for_pow : M unit := + (* + 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. + *) + let* header_data_without_pow_artefacts := (* TODO expression *) in + (* TODO statement *) + + +Definition validate_proof_of_work : 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. + *) + let* header_hash := generate_header_hash_for_pow (| + header + |) in + let* cache := ethereum.ethash.generate_cache (| + header.["number"] + |) in + (* TODO assignment *) + (* TODO statement *) + let* limit := (* TODO expression *) in + (* TODO statement *) + + +Definition check_transaction : M unit := + (* + 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 *) + let* sender_address := recover_sender (| + chain_id, + tx + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition make_receipt : M unit := + (* + 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. + *) + let* receipt := blocks.Receipt (| + + |) in + (* TODO statement *) + + +Definition apply_body : M unit := + (* + 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. + *) + let* gas_available := block_gas_limit in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* pay_rewards (| + state, + block_number, + coinbase, + ommers + |) in + let* block_gas_used := (* TODO expression *) in + let* block_logs_bloom := bloom.logs_bloom (| + block_logs + |) in + (* TODO statement *) + + +Definition validate_ommers : 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. + *) + let* block_hash := rlp.["rlp_hash"] (| + block_header + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* ommers_hashes := (* TODO expression *) in + (* TODO statement *) + let* recent_canonical_blocks := (* TODO expression *) in + let* recent_canonical_block_hashes := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition pay_rewards : 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. + *) + let* ommer_count := ethereum_types.numeric.U256 (| + len (| + ommers + |) + |) in + let* miner_reward := (* TODO expression *) in + do* state.create_ether (| + state, + coinbase, + miner_reward + |) in + (* TODO statement *) + + +Definition process_transaction : M unit := + (* + 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 *) + let* sender := env.["origin"] in + let* sender_account := state.get_account (| + env.["state"], + sender + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* effective_gas_fee := (* TODO expression *) in + let* gas := (* TODO expression *) in + do* state.increment_nonce (| + env.["state"], + sender + |) in + let* sender_balance_after_gas_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + ethereum_types.numeric.U256 (| + sender_balance_after_gas_fee + |) + |) in + let* preaccessed_addresses := set (| + + |) in + let* preaccessed_storage_keys := set (| + + |) in + (* TODO statement *) + let* message := utils.message.prepare_message (| + sender, + tx.["to"], + tx.["value"], + tx.["data"], + gas, + env + |) in + let* output := vm.interpreter.process_message_call (| + message, + env + |) in + let* gas_used := (* TODO expression *) in + let* gas_refund := min (| + (* TODO expression *), + ethereum_types.numeric.Uint (| + output.["refund_counter"] + |) + |) in + let* gas_refund_amount := (* TODO expression *) in + let* priority_fee_per_gas := (* TODO expression *) in + let* transaction_fee := (* TODO expression *) in + let* total_gas_used := (* TODO expression *) in + let* sender_balance_after_refund := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + sender_balance_after_refund + |) in + let* coinbase_balance_after_mining_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_transaction : M unit := + (* + 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 *) + + +Definition calculate_intrinsic_cost : M unit := + (* + 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. + *) + let* data_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + let* access_list_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + + +Definition recover_sender : M unit := + (* + 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 *) + + +Definition signing_hash_pre155 : M unit := + (* + 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 *) + + +Definition signing_hash_155 : M unit := + (* + 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 *) + + +Definition signing_hash_2930 : M unit := + (* + 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 *) + + +Definition signing_hash_1559 : M unit := + (* + 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 *) + + +Definition compute_header_hash : M unit := + (* + 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 *) + + +Definition check_gas_limit : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_block_difficulty : M unit := + (* + 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. + *) + let* offset := (* TODO expression *) in + let* difficulty := (* TODO expression *) in + let* num_bomb_periods := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..14de99d5e5 --- /dev/null +++ b/coq/ethereum/gray_glacier/fork_types.v @@ -0,0 +1,29 @@ +(* +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 ..crypto.hash. + +Definition encode_account : M unit := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + 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..dba869a9be --- /dev/null +++ b/coq/ethereum/gray_glacier/state.v @@ -0,0 +1,593 @@ +(* +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 gray_glacier.fork_types. +Require gray_glacier.trie. + +Definition close_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 *) + + +Definition begin_transaction : 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* state.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + + +Definition commit_transaction : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* state.["_snapshots"].["pop"] (| + + |) in + (* TODO statement *) + + +Definition rollback_transaction : 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 *) + + +Definition get_account : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition get_account_optional : M unit := + (* + 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. + *) + let* account := trie.trie_get (| + state.["_main_trie"], + address + |) in + (* TODO statement *) + + +Definition set_account : 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 (| + state.["_main_trie"], + address, + account + |) in + + +Definition destroy_account : 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* destroy_storage (| + state, + address + |) in + do* set_account (| + state, + address, + (* TODO expression *) + |) in + + +Definition destroy_storage : 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 *) + + +Definition mark_account_created : 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* state.["created_accounts"].["add"] (| + address + |) in + + +Definition get_storage : M unit := + (* + 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. + *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_storage : 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 *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition storage_root : M unit := + (* + 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 *) + + +Definition state_root : M unit := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition account_exists : M unit := + (* + 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 *) + + +Definition account_has_code_or_nonce : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_empty : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition account_exists_and_is_empty : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_alive : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition modify_state : M unit := + (* + Modify an `Account` in the `State`. + *) + do* set_account (| + state, + address, + ethereum_types.frozen.modify (| + get_account (| + state, + address + |), + f + |) + |) in + + +Definition move_ether : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* modify_state (| + state, + sender_address, + reduce_sender_balance + |) in + do* modify_state (| + state, + recipient_address, + increase_recipient_balance + |) in + + +Definition set_account_balance : 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* modify_state (| + state, + address, + set_balance + |) in + + +Definition touch_account : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + + +Definition increment_nonce : 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* modify_state (| + state, + address, + increase_nonce + |) in + + +Definition set_code : 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* modify_state (| + state, + address, + write_code + |) in + + +Definition create_ether : 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* modify_state (| + state, + address, + increase_balance + |) in + + +Definition get_storage_original : M unit := + (* + 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 *) + let* original_account_trie := original_trie.["get"] (| + address + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + 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..7b848450cc --- /dev/null +++ b/coq/ethereum/gray_glacier/transactions.v @@ -0,0 +1,27 @@ +(* +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 gray_glacier.exceptions. +Require gray_glacier.fork_types. + +Definition encode_transaction : M unit := + (* + Encode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + + +Definition decode_transaction : M unit := + (* + Decode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + 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..548de91e1c --- /dev/null +++ b/coq/ethereum/gray_glacier/trie.v @@ -0,0 +1,274 @@ +(* +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 : M unit := + (* + 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 *) + let* encoded := rlp.["encode"] (| + unencoded + |) in + (* TODO statement *) + + +Definition encode_node : M unit := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + + +Definition copy_trie : M unit := + (* + 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 *) + + +Definition trie_set : 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 *) + + +Definition trie_get : M unit := + (* + 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 *) + + +Definition common_prefix_length : M unit := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition nibble_list_to_compact : M unit := + (* + 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. + *) + let* compact := bytearray (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_nibble_list : M unit := + (* + 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. + *) + let* nibble_list := bytearray (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _prepare_trie : M unit := + (* + 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 *) + + +Definition root : M unit := + (* + 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. + *) + let* obj := _prepare_trie (| + trie, + get_storage_root + |) in + let* root_node := encode_internal_node (| + patricialize (| + obj, + Uint (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + + +Definition patricialize : M unit := + (* + 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 *) + let* arbitrary_key := next (| + iter (| + obj + |) + |) in + (* TODO statement *) + let* substring := (* TODO expression *) in + let* prefix_length := len (| + substring + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..beff4482b1 --- /dev/null +++ b/coq/ethereum/gray_glacier/utils/__init__.v @@ -0,0 +1,4 @@ +(* +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..d40ce2219c --- /dev/null +++ b/coq/ethereum/gray_glacier/utils/address.v @@ -0,0 +1,99 @@ +(* +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 gray_glacier.fork_types. + +Definition to_address : M unit := + (* + 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 *) + + +Definition compute_contract_address : M unit := + (* + 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. + *) + let* computed_address := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *) + |) + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition compute_create2_contract_address : M unit := + (* + 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. + *) + let* preimage := (* TODO expression *) in + let* computed_address := ethereum.crypto.hash.keccak256 (| + preimage + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + 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..1f3005468c --- /dev/null +++ b/coq/ethereum/gray_glacier/utils/hexadecimal.v @@ -0,0 +1,68 @@ +(* +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 gray_glacier.fork_types. + +Definition hex_to_root : M unit := + (* + 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 *) + + +Definition hex_to_bloom : M unit := + (* + 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 *) + + +Definition hex_to_address : M unit := + (* + 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 *) + 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..6d16f08c28 --- /dev/null +++ b/coq/ethereum/gray_glacier/utils/message.v @@ -0,0 +1,82 @@ +(* +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 gray_glacier.fork_types. +Require gray_glacier.state. +Require gray_glacier.vm. +Require gray_glacier.vm.precompiled_contracts.mapping. +Require gray_glacier.utils.address. + +Definition prepare_message : M unit := + (* + 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 *) + let* accessed_addresses := set (| + + |) in + do* accessed_addresses.["add"] (| + current_target + |) in + do* accessed_addresses.["add"] (| + caller + |) in + do* accessed_addresses.["update"] (| + vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS.["keys"] (| + + |) + |) in + do* accessed_addresses.["update"] (| + preaccessed_addresses + |) in + (* TODO statement *) + 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..5bce4bde9d --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/__init__.v @@ -0,0 +1,69 @@ +(* +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 gray_glacier.blocks. +Require gray_glacier.fork_types. +Require gray_glacier.state. +Require gray_glacier.vm.precompiled_contracts. + +Definition incorporate_child_on_success : 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* evm.["accounts_to_delete"].["update"] (| + child_evm.["accounts_to_delete"] + |) in + do* evm.["touched_accounts"].["update"] (| + child_evm.["touched_accounts"] + |) in + (* TODO statement *) + do* evm.["accessed_addresses"].["update"] (| + child_evm.["accessed_addresses"] + |) in + do* evm.["accessed_storage_keys"].["update"] (| + child_evm.["accessed_storage_keys"] + |) in + + +Definition incorporate_child_on_error : 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 *) + (* TODO statement *) + 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..1784494410 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/exceptions.v @@ -0,0 +1,15 @@ +(* +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..eaa619555b --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/gas.v @@ -0,0 +1,151 @@ +(* +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 gray_glacier.vm.exceptions. + +Definition charge_gas : 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 (| + int (| + amount + |) + |) + |) in + (* TODO statement *) + + +Definition calculate_memory_gas_cost : M unit := + (* + 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. + *) + let* size_in_words := (* TODO expression *) in + let* linear_cost := (* TODO expression *) in + let* quadratic_cost := (* TODO expression *) in + let* total_gas_cost := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_gas_extend_memory : M unit := + (* + 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` + *) + let* size_to_extend := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* to_be_paid := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* current_size := ethereum_types.numeric.Uint (| + len (| + memory + |) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_message_call_gas : M unit := + (* + 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` + *) + let* call_stipend := (* TODO expression *) in + (* TODO statement *) + let* gas := min (| + gas, + max_message_call_gas (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + + +Definition max_message_call_gas : M unit := + (* + 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 *) + 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..b36b1ebfef --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/__init__.v @@ -0,0 +1,15 @@ +(* +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..ac2876fdf3 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/arithmetic.v @@ -0,0 +1,387 @@ +(* +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 gray_glacier.vm.gas. +Require gray_glacier.vm.stack. + +Definition add : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_add"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition sub : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_sub"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mul : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + let* result := x.["wrapping_mul"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition div : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |) in + let* divisor := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + quotient + |) in + (* TODO statement *) + + +Definition sdiv : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* divisor := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + quotient + |) + |) in + (* TODO statement *) + + +Definition mod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + remainder + |) in + (* TODO statement *) + + +Definition smod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* y := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + remainder + |) + |) in + (* TODO statement *) + + +Definition addmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mulmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition exp : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* base := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent_bits := exponent.["bit_length"] (| + + |) in + let* exponent_bytes := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* result := ethereum_types.numeric.U256 (| + pow (| + base, + exponent, + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signextend : 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. + + *) + let* byte_num := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..af59c57694 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/bitwise.v @@ -0,0 +1,245 @@ +(* +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 gray_glacier.vm.gas. +Require gray_glacier.vm.stack. + +Definition bitwise_and : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_or : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_xor : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_not : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition get_byte : 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. + + *) + let* byte_index := stack.pop (| + evm.["stack"] + |) in + let* word := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shl : 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. + *) + let* shift := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shr : 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. + *) + let* shift := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_sar : 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. + *) + let* shift := int (| + stack.pop (| + evm.["stack"] + |) + |) in + let* signed_value := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..f8d9360c10 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/block.v @@ -0,0 +1,207 @@ +(* +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 gray_glacier.vm.gas. +Require gray_glacier.vm.stack. + +Definition block_hash : 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. + + *) + let* block_number := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOCK_HASH + |) in + let* max_block_number := (* TODO expression *) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + + +Definition coinbase : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["coinbase"] + |) + |) in + (* TODO statement *) + + +Definition timestamp : 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 (| + evm.["stack"], + evm.["env"].["time"] + |) in + (* TODO statement *) + + +Definition number : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["number"] + |) + |) in + (* TODO statement *) + + +Definition difficulty : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["difficulty"] + |) + |) in + (* TODO statement *) + + +Definition gas_limit : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_limit"] + |) + |) in + (* TODO statement *) + + +Definition chain_id : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["chain_id"] + |) + |) in + (* TODO statement *) + 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..7cef056882 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/comparison.v @@ -0,0 +1,206 @@ +(* +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 gray_glacier.vm.gas. +Require gray_glacier.vm.stack. + +Definition less_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_less_than : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition greater_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_greater_than : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition equal : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition is_zero : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..1f88e4a395 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/control_flow.v @@ -0,0 +1,156 @@ +(* +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 gray_glacier.vm.gas. +Require gray_glacier.vm.exceptions. +Require gray_glacier.vm.stack. + +Definition stop : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition jump : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_MID + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition jumpi : 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. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* conditional_value := stack.pop (| + evm.["stack"] + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_HIGH + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition pc : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["pc"] + |) + |) in + (* TODO statement *) + + +Definition gas_left : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + + +Definition jumpdest : 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 *) + (* TODO statement *) + 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..7a2b15966a --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/environment.v @@ -0,0 +1,568 @@ +(* +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 gray_glacier.fork_types. +Require gray_glacier.state. +Require gray_glacier.utils.address. +Require gray_glacier.vm.memory. +Require gray_glacier.vm.exceptions. +Require gray_glacier.vm.gas. +Require gray_glacier.vm.stack. + +Definition address : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["current_target"] + |) + |) in + (* TODO statement *) + + +Definition balance : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* balance := state.get_account (| + evm.["env"].["state"], + address + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition origin : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["origin"] + |) + |) in + (* TODO statement *) + + +Definition caller : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["caller"] + |) + |) in + (* TODO statement *) + + +Definition callvalue : 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 (| + evm.["stack"], + evm.["message"].["value"] + |) in + (* TODO statement *) + + +Definition calldataload : 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. + + *) + let* start_index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + start_index, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + value + |) + |) in + (* TODO statement *) + + +Definition calldatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["message"].["data"] + |) + |) + |) in + (* TODO statement *) + + +Definition calldatacopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* data_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + data_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition codesize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["code"] + |) + |) + |) in + (* TODO statement *) + + +Definition codecopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["code"], + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition gasprice : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_price"] + |) + |) in + (* TODO statement *) + + +Definition extcodesize : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* codesize := ethereum_types.numeric.U256 (| + len (| + state.get_account (| + evm.["env"].["state"], + address + |).["code"] + |) + |) in + do* stack.push (| + evm.["stack"], + codesize + |) in + (* TODO statement *) + + +Definition extcodecopy : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* code := state.get_account (| + evm.["env"].["state"], + address + |).["code"] in + let* value := vm.memory.buffer_read (| + code, + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition returndatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["return_data"] + |) + |) + |) in + (* TODO statement *) + + +Definition returndatacopy : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* return_data_start_position := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition extcodehash : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* account := state.get_account (| + evm.["env"].["state"], + address + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + codehash + |) in + (* TODO statement *) + + +Definition self_balance : 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 + let* balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition base_fee : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["base_fee_per_gas"] + |) + |) in + (* TODO statement *) + 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..416b27d9c9 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/keccak.v @@ -0,0 +1,67 @@ +(* +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 gray_glacier.vm.gas. +Require gray_glacier.vm.memory. +Require gray_glacier.vm.stack. + +Definition keccak : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* word_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + let* hash := ethereum.crypto.hash.keccak256 (| + data + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + 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..91a8aefda9 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/log.v @@ -0,0 +1,61 @@ +(* +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 gray_glacier.blocks. +Require gray_glacier.vm.exceptions. +Require gray_glacier.vm.gas. +Require gray_glacier.vm.memory. +Require gray_glacier.vm.stack. + +Definition log_n : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* topics := (* TODO expression *) in + (* TODO statement *) + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* log_entry := blocks.Log (| + + |) in + (* TODO assignment *) + (* TODO statement *) + 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..de111d5c5d --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/memory.v @@ -0,0 +1,158 @@ +(* +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 gray_glacier.vm.gas. +Require gray_glacier.vm.memory. +Require gray_glacier.vm.stack. + +Definition mstore : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* memory.memory_write (| + evm.["memory"], + start_position, + value + |) in + (* TODO statement *) + + +Definition mstore8 : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + (* TODO expression *) + |) in + do* memory.memory_write (| + evm.["memory"], + start_position, + normalized_bytes_value + |) in + (* TODO statement *) + + +Definition mload : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.memory_read_bytes (| + evm.["memory"], + start_position, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition msize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["memory"] + |) + |) + |) in + (* TODO statement *) + 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..568e61ea04 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/stack.v @@ -0,0 +1,133 @@ +(* +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 gray_glacier.vm.exceptions. +Require gray_glacier.vm.gas. +Require gray_glacier.vm.memory. + +Definition pop : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* stack.["pop"] (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BASE + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition push_n : 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 + let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + evm.["code"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + num_bytes + |) + |) + |) in + do* stack.["push"] (| + evm.["stack"], + data_to_push + |) in + (* TODO statement *) + + +Definition dup_n : 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 *) + let* data_to_duplicate := (* TODO expression *) in + do* stack.["push"] (| + evm.["stack"], + data_to_duplicate + |) in + (* TODO statement *) + + +Definition swap_n : 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 *) + (* TODO statement *) + 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..e6c64412e9 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/storage.v @@ -0,0 +1,97 @@ +(* +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 gray_glacier.state. +Require gray_glacier.vm.exceptions. +Require gray_glacier.vm.gas. +Require gray_glacier.vm.stack. + +Definition sload : 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. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + (* TODO statement *) + let* value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition sstore : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + (* TODO statement *) + let* original_value := state.get_storage_original (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + let* current_value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + let* gas_cost := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + do* state.set_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + 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..0d1d237a2a --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/system.v @@ -0,0 +1,585 @@ +(* +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 gray_glacier.fork_types. +Require gray_glacier.state. +Require gray_glacier.utils.address. +Require gray_glacier.vm.exceptions. +Require gray_glacier.vm.gas. +Require gray_glacier.vm.memory. +Require gray_glacier.vm.stack. + +Definition generic_create : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + do* evm.["accessed_addresses"].["add"] (| + contract_address + |) in + let* create_message_gas := gas.max_message_call_gas (| + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + let* sender_address := evm.["message"].["current_target"] in + let* sender := state.get_account (| + evm.["env"].["state"], + sender_address + |) in + (* TODO statement *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) in + do* state.increment_nonce (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |) in + let* child_message := Message (| + + |) in + let* child_evm := process_create_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + + +Definition create : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_contract_address (| + evm.["message"].["current_target"], + state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["nonce"] + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size + |) in + (* TODO statement *) + + +Definition create2 : 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. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* salt := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* call_data_words := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_create2_contract_address (| + evm.["message"].["current_target"], + salt, + memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size + |) in + (* TODO statement *) + + +Definition return_ : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + + +Definition generic_call : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_input_start_position, + memory_input_size + |) in + let* code := state.get_account (| + evm.["env"].["state"], + code_address + |).["code"] in + let* child_message := Message (| + + |) in + let* child_evm := process_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + let* actual_output_size := min (| + memory_output_size, + ethereum_types.numeric.U256 (| + len (| + child_evm.["output"] + |) + |) + |) in + do* memory.memory_write (| + evm.["memory"], + memory_output_start_position, + (* TODO expression *) + |) in + + +Definition call : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* create_gas_cost := (* TODO expression *) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition callcode : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* to := evm.["message"].["current_target"] in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition selfdestruct : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* beneficiary := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* gas_cost := gas.GAS_SELF_DESTRUCT in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + let* originator := evm.["message"].["current_target"] in + let* beneficiary_balance := state.get_account (| + evm.["env"].["state"], + beneficiary + |).["balance"] in + let* originator_balance := state.get_account (| + evm.["env"].["state"], + originator + |).["balance"] in + do* state.set_account_balance (| + evm.["env"].["state"], + beneficiary, + (* TODO expression *) + |) in + do* state.set_account_balance (| + evm.["env"].["state"], + originator, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* evm.["accounts_to_delete"].["add"] (| + originator + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition delegatecall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + access_gas_cost + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + evm.["message"].["value"], + evm.["message"].["caller"], + evm.["message"].["current_target"], + code_address, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition staticcall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + access_gas_cost + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + evm.["message"].["current_target"], + to, + to, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition revert : 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. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + extend_memory.["cost"] + |) in + (* TODO statement *) + let* output := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + 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..77619bf01a --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/interpreter.v @@ -0,0 +1,159 @@ +(* +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 gray_glacier.blocks. +Require gray_glacier.fork_types. +Require gray_glacier.state. +Require gray_glacier.vm. +Require gray_glacier.vm.gas. +Require gray_glacier.vm.precompiled_contracts.mapping. +Require gray_glacier.vm.exceptions. +Require gray_glacier.vm.instructions. +Require gray_glacier.vm.runtime. + +Definition process_message_call : M unit := + (* + 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 *) + let* tx_end := ethereum.trace.TransactionEnd (| + (* TODO expression *), + evm.["output"], + evm.["error"] + |) in + do* ethereum.trace.evm_trace (| + evm, + tx_end + |) in + (* TODO statement *) + + +Definition process_create_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.destroy_storage (| + env.["state"], + message.["current_target"] + |) in + do* state.mark_account_created (| + env.["state"], + message.["current_target"] + |) in + do* state.increment_nonce (| + env.["state"], + message.["current_target"] + |) in + let* evm := process_message (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.touch_account (| + env.["state"], + message.["current_target"] + |) in + (* TODO statement *) + let* evm := execute_code (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition execute_code : M unit := + (* + 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 + *) + let* code := message.["code"] in + let* valid_jump_destinations := runtime.get_valid_jump_destinations (| + code + |) in + let* evm := Evm (| + + |) in + (* TODO statement *) + (* TODO statement *) + 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..94b6a44639 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/memory.v @@ -0,0 +1,75 @@ +(* +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 : 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 *) + + +Definition memory_read_bytes : M unit := + (* + 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 *) + + +Definition buffer_read : M unit := + (* + 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 *) + 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..41776f4ca0 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/__init__.v @@ -0,0 +1,16 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require 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..566d466ee5 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,187 @@ +(* +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 gray_glacier.vm. +Require gray_glacier.vm.gas. +Require gray_glacier.vm.memory. +Require gray_glacier.vm.exceptions. + +Definition alt_bn128_add : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* x1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x1_bytes + |) + |) in + let* y1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y1_bytes + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := (* TODO expression *) in + (* TODO assignment *) + + +Definition alt_bn128_mul : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* n := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := p0.["mul_by"] (| + n + |) in + (* TODO assignment *) + + +Definition alt_bn128_pairing_check : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..583aa354a4 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,41 @@ +(* +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 gray_glacier.vm. +Require gray_glacier.vm.gas. +Require gray_glacier.vm.exceptions. + +Definition blake2f : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + (* TODO statement *) + let* blake2b := ethereum.crypto.blake2.Blake2b (| + + |) in + (* TODO assignment *) + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + 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..1ba9ae7ae9 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,93 @@ +(* +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 gray_glacier.vm. +Require gray_glacier.vm.gas. +Require gray_glacier.vm.memory. + +Definition ecrecover : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_ECRECOVER + |) in + let* message_hash_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* message_hash := ethereum.crypto.hash.Hash32 (| + message_hash_bytes + |) in + let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + address, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..bb810f154b --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/identity.v @@ -0,0 +1,36 @@ +(* +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 gray_glacier.vm. +Require gray_glacier.vm.gas. + +Definition identity : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..41a63293b6 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/mapping.v @@ -0,0 +1,23 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require gray_glacier.fork_types. +Require gray_glacier.vm.precompiled_contracts.alt_bn128. +Require gray_glacier.vm.precompiled_contracts.blake2f. +Require gray_glacier.vm.precompiled_contracts.ecrecover. +Require gray_glacier.vm.precompiled_contracts.identity. +Require gray_glacier.vm.precompiled_contracts.modexp. +Require gray_glacier.vm.precompiled_contracts.ripemd160. +Require 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..8a4434582b --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/modexp.v @@ -0,0 +1,203 @@ +(* +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 gray_glacier.vm. +Require gray_glacier.vm.gas. +Require gray_glacier.vm.memory. + +Definition modexp : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + let* data := evm.["message"].["data"] in + let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_start := (* TODO expression *) in + let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + min (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + exp_length + |) + |) + |) in + do* vm.gas.charge_gas (| + evm, + gas_cost (| + base_length, + modulus_length, + exp_length, + exp_head + |) + |) in + (* TODO statement *) + let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + base_length + |) + |) in + let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + exp_length + |) + |) in + let* modulus_start := (* TODO expression *) in + let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + modulus_start, + modulus_length + |) + |) in + (* TODO statement *) + + +Definition complexity : M unit := + (* + 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. + *) + let* max_length := max (| + ethereum_types.numeric.Uint (| + base_length + |), + ethereum_types.numeric.Uint (| + modulus_length + |) + |) in + let* words := (* TODO expression *) in + (* TODO statement *) + + +Definition iterations : M unit := + (* + 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 *) + + +Definition gas_cost : M unit := + (* + 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. + *) + let* multiplication_complexity := complexity (| + base_length, + modulus_length + |) in + let* iteration_count := iterations (| + exponent_length, + exponent_head + |) in + let* cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..bc5e73dd3c --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,42 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + let* hash_bytes := hashlib.["new"] (| + (* TODO expression *), + data + |).["digest"] (| + + |) in + let* padded_hash := left_pad_zero_bytes (| + hash_bytes, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..da6972d411 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/sha256.v @@ -0,0 +1,32 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..37ec67279f --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/runtime.v @@ -0,0 +1,49 @@ +(* +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 gray_glacier.vm.instructions. + +Definition get_valid_jump_destinations : M unit := + (* + 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. + *) + let* valid_jump_destinations := set (| + + |) in + let* pc := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..f47503ffda --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/stack.v @@ -0,0 +1,53 @@ +(* +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 gray_glacier.vm.exceptions. + +Definition pop : M unit := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + + +Definition push : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + 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..ed0ab80f91 --- /dev/null +++ b/coq/ethereum/homestead/__init__.v @@ -0,0 +1,8 @@ +(* +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..530db3d996 --- /dev/null +++ b/coq/ethereum/homestead/blocks.v @@ -0,0 +1,19 @@ +(* +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 ..crypto.hash. +Require homestead.fork_types. +Require 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..0b169c3e69 --- /dev/null +++ b/coq/ethereum/homestead/bloom.v @@ -0,0 +1,66 @@ +(* +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 homestead.blocks. +Require homestead.fork_types. + +Definition add_to_bloom : 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. + *) + let* hash := ethereum.crypto.hash.keccak256 (| + bloom_entry + |) in + (* TODO statement *) + + +Definition logs_bloom : M unit := + (* + 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 *) + 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..bcccf731cd --- /dev/null +++ b/coq/ethereum/homestead/fork.v @@ -0,0 +1,744 @@ +(* +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 homestead.blocks. +Require homestead.bloom. +Require homestead.fork_types. +Require homestead.state. +Require homestead.transactions. +Require homestead.trie. +Require homestead.utils.message. +Require homestead.vm.interpreter. + +Definition apply_fork : M unit := + (* + 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 *) + + +Definition get_last_256_block_hashes : M unit := + (* + 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. + *) + let* recent_blocks := (* TODO expression *) in + (* TODO statement *) + let* recent_block_hashes := (* TODO expression *) in + (* TODO statement *) + let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *).["header"] + |) + |) in + do* recent_block_hashes.["append"] (| + most_recent_block_hash + |) in + (* TODO statement *) + + +Definition state_transition : 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`. + *) + let* parent_header := (* TODO expression *).["header"] in + do* validate_header (| + block.["header"], + parent_header + |) in + do* validate_ommers (| + block.["ommers"], + block.["header"], + chain + |) in + let* apply_body_output := apply_body (| + chain.["state"], + get_last_256_block_hashes (| + chain + |), + block.["header"].["coinbase"], + block.["header"].["number"], + block.["header"].["gas_limit"], + block.["header"].["timestamp"], + block.["header"].["difficulty"], + block.["transactions"], + block.["ommers"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* chain.["blocks"].["append"] (| + block + |) in + (* TODO statement *) + + +Definition validate_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 *) + let* block_difficulty := calculate_block_difficulty (| + header.["number"], + header.["timestamp"], + parent_header.["timestamp"], + parent_header.["difficulty"] + |) in + (* TODO statement *) + let* block_parent_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + parent_header + |) + |) in + (* TODO statement *) + do* validate_proof_of_work (| + header + |) in + + +Definition generate_header_hash_for_pow : M unit := + (* + 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. + *) + let* header_data_without_pow_artefacts := (* TODO expression *) in + (* TODO statement *) + + +Definition validate_proof_of_work : 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. + *) + let* header_hash := generate_header_hash_for_pow (| + header + |) in + let* cache := ethereum.ethash.generate_cache (| + header.["number"] + |) in + (* TODO assignment *) + (* TODO statement *) + let* limit := (* TODO expression *) in + (* TODO statement *) + + +Definition check_transaction : M unit := + (* + 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 *) + let* sender_address := recover_sender (| + tx + |) in + (* TODO statement *) + + +Definition make_receipt : M unit := + (* + 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. + *) + let* receipt := blocks.Receipt (| + + |) in + (* TODO statement *) + + +Definition apply_body : M unit := + (* + 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. + *) + let* gas_available := block_gas_limit in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* pay_rewards (| + state, + block_number, + coinbase, + ommers + |) in + let* block_gas_used := (* TODO expression *) in + let* block_logs_bloom := bloom.logs_bloom (| + block_logs + |) in + (* TODO statement *) + + +Definition validate_ommers : 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. + *) + let* block_hash := rlp.["rlp_hash"] (| + block_header + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* ommers_hashes := (* TODO expression *) in + (* TODO statement *) + let* recent_canonical_blocks := (* TODO expression *) in + let* recent_canonical_block_hashes := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition pay_rewards : 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. + *) + let* ommer_count := ethereum_types.numeric.U256 (| + len (| + ommers + |) + |) in + let* miner_reward := (* TODO expression *) in + do* state.create_ether (| + state, + coinbase, + miner_reward + |) in + (* TODO statement *) + + +Definition process_transaction : M unit := + (* + 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 *) + let* sender := env.["origin"] in + let* sender_account := state.get_account (| + env.["state"], + sender + |) in + let* gas_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* gas := (* TODO expression *) in + do* state.increment_nonce (| + env.["state"], + sender + |) in + let* sender_balance_after_gas_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + ethereum_types.numeric.U256 (| + sender_balance_after_gas_fee + |) + |) in + let* message := utils.message.prepare_message (| + sender, + tx.["to"], + tx.["value"], + tx.["data"], + gas, + env + |) in + let* output := vm.interpreter.process_message_call (| + message, + env + |) in + let* gas_used := (* TODO expression *) in + let* gas_refund := min (| + (* TODO expression *), + ethereum_types.numeric.Uint (| + output.["refund_counter"] + |) + |) in + let* gas_refund_amount := (* TODO expression *) in + let* transaction_fee := (* TODO expression *) in + let* total_gas_used := (* TODO expression *) in + let* sender_balance_after_refund := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + sender_balance_after_refund + |) in + let* coinbase_balance_after_mining_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + env.["coinbase"], + coinbase_balance_after_mining_fee + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition validate_transaction : M unit := + (* + 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 *) + + +Definition calculate_intrinsic_cost : M unit := + (* + 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. + *) + let* data_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition recover_sender : M unit := + (* + 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 *) + let* public_key := ethereum.crypto.elliptic_curve.secp256k1_recover (| + r, + s, + (* TODO expression *), + signing_hash (| + tx + |) + |) in + (* TODO statement *) + + +Definition signing_hash : M unit := + (* + 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 *) + + +Definition compute_header_hash : M unit := + (* + 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 *) + + +Definition check_gas_limit : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_block_difficulty : M unit := + (* + 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. + *) + let* offset := (* TODO expression *) in + let* difficulty := (* TODO expression *) in + let* num_bomb_periods := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..14de99d5e5 --- /dev/null +++ b/coq/ethereum/homestead/fork_types.v @@ -0,0 +1,29 @@ +(* +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 ..crypto.hash. + +Definition encode_account : M unit := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + 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..2c93111c7a --- /dev/null +++ b/coq/ethereum/homestead/state.v @@ -0,0 +1,471 @@ +(* +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 homestead.fork_types. +Require homestead.trie. + +Definition close_state : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition begin_transaction : 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* state.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + + +Definition commit_transaction : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* state.["_snapshots"].["pop"] (| + + |) in + + +Definition rollback_transaction : 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 *) + + +Definition get_account : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition get_account_optional : M unit := + (* + 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. + *) + let* account := trie.trie_get (| + state.["_main_trie"], + address + |) in + (* TODO statement *) + + +Definition set_account : 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 (| + state.["_main_trie"], + address, + account + |) in + + +Definition destroy_account : 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* destroy_storage (| + state, + address + |) in + do* set_account (| + state, + address, + (* TODO expression *) + |) in + + +Definition destroy_storage : 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 *) + + +Definition get_storage : M unit := + (* + 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. + *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_storage : 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 *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition storage_root : M unit := + (* + 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 *) + + +Definition state_root : M unit := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition account_exists : M unit := + (* + 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 *) + + +Definition account_has_code_or_nonce : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition modify_state : M unit := + (* + Modify an `Account` in the `State`. + *) + do* set_account (| + state, + address, + ethereum_types.frozen.modify (| + get_account (| + state, + address + |), + f + |) + |) in + + +Definition move_ether : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* modify_state (| + state, + sender_address, + reduce_sender_balance + |) in + do* modify_state (| + state, + recipient_address, + increase_recipient_balance + |) in + + +Definition set_account_balance : 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* modify_state (| + state, + address, + set_balance + |) in + + +Definition touch_account : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + + +Definition increment_nonce : 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* modify_state (| + state, + address, + increase_nonce + |) in + + +Definition set_code : 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* modify_state (| + state, + address, + write_code + |) in + + +Definition create_ether : 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* modify_state (| + state, + address, + increase_balance + |) in + 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..4811f98727 --- /dev/null +++ b/coq/ethereum/homestead/transactions.v @@ -0,0 +1,12 @@ +(* +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 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..548de91e1c --- /dev/null +++ b/coq/ethereum/homestead/trie.v @@ -0,0 +1,274 @@ +(* +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 : M unit := + (* + 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 *) + let* encoded := rlp.["encode"] (| + unencoded + |) in + (* TODO statement *) + + +Definition encode_node : M unit := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + + +Definition copy_trie : M unit := + (* + 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 *) + + +Definition trie_set : 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 *) + + +Definition trie_get : M unit := + (* + 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 *) + + +Definition common_prefix_length : M unit := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition nibble_list_to_compact : M unit := + (* + 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. + *) + let* compact := bytearray (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_nibble_list : M unit := + (* + 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. + *) + let* nibble_list := bytearray (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _prepare_trie : M unit := + (* + 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 *) + + +Definition root : M unit := + (* + 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. + *) + let* obj := _prepare_trie (| + trie, + get_storage_root + |) in + let* root_node := encode_internal_node (| + patricialize (| + obj, + Uint (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + + +Definition patricialize : M unit := + (* + 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 *) + let* arbitrary_key := next (| + iter (| + obj + |) + |) in + (* TODO statement *) + let* substring := (* TODO expression *) in + let* prefix_length := len (| + substring + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..beff4482b1 --- /dev/null +++ b/coq/ethereum/homestead/utils/__init__.v @@ -0,0 +1,4 @@ +(* +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..5399c03175 --- /dev/null +++ b/coq/ethereum/homestead/utils/address.v @@ -0,0 +1,66 @@ +(* +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 homestead.fork_types. + +Definition to_address : M unit := + (* + 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 *) + + +Definition compute_contract_address : M unit := + (* + 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. + *) + let* computed_address := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *) + |) + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + 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..eb2a313bdf --- /dev/null +++ b/coq/ethereum/homestead/utils/hexadecimal.v @@ -0,0 +1,68 @@ +(* +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 homestead.fork_types. + +Definition hex_to_root : M unit := + (* + 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 *) + + +Definition hex_to_bloom : M unit := + (* + 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 *) + + +Definition hex_to_address : M unit := + (* + 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 *) + 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..557b041553 --- /dev/null +++ b/coq/ethereum/homestead/utils/message.v @@ -0,0 +1,55 @@ +(* +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 homestead.fork_types. +Require homestead.state. +Require homestead.vm. +Require homestead.utils.address. + +Definition prepare_message : M unit := + (* + 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 *) + 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..e3cb8fad46 --- /dev/null +++ b/coq/ethereum/homestead/vm/__init__.v @@ -0,0 +1,56 @@ +(* +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 homestead.blocks. +Require homestead.fork_types. +Require homestead.state. + +Definition incorporate_child_on_success : 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* evm.["accounts_to_delete"].["update"] (| + child_evm.["accounts_to_delete"] + |) in + + +Definition incorporate_child_on_error : 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 *) + 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..1784494410 --- /dev/null +++ b/coq/ethereum/homestead/vm/exceptions.v @@ -0,0 +1,15 @@ +(* +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..96060b022b --- /dev/null +++ b/coq/ethereum/homestead/vm/gas.v @@ -0,0 +1,125 @@ +(* +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 homestead.fork_types. +Require homestead.state. +Require homestead.vm.exceptions. + +Definition charge_gas : 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 (| + int (| + amount + |) + |) + |) in + (* TODO statement *) + + +Definition calculate_memory_gas_cost : M unit := + (* + 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. + *) + let* size_in_words := (* TODO expression *) in + let* linear_cost := (* TODO expression *) in + let* quadratic_cost := (* TODO expression *) in + let* total_gas_cost := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_gas_extend_memory : M unit := + (* + 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` + *) + let* size_to_extend := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* to_be_paid := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* current_size := ethereum_types.numeric.Uint (| + len (| + memory + |) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_message_call_gas : M unit := + (* + 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` + *) + let* create_gas_cost := (* TODO expression *) in + let* transfer_gas_cost := (* TODO expression *) in + let* cost := (* TODO expression *) in + let* stipend := (* TODO expression *) in + (* TODO statement *) + 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..b36b1ebfef --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/__init__.v @@ -0,0 +1,15 @@ +(* +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..7e1cb83ac1 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/arithmetic.v @@ -0,0 +1,387 @@ +(* +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 homestead.vm.gas. +Require homestead.vm.stack. + +Definition add : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_add"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition sub : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_sub"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mul : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + let* result := x.["wrapping_mul"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition div : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |) in + let* divisor := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + quotient + |) in + (* TODO statement *) + + +Definition sdiv : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* divisor := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + quotient + |) + |) in + (* TODO statement *) + + +Definition mod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + remainder + |) in + (* TODO statement *) + + +Definition smod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* y := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + remainder + |) + |) in + (* TODO statement *) + + +Definition addmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mulmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition exp : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* base := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent_bits := exponent.["bit_length"] (| + + |) in + let* exponent_bytes := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* result := ethereum_types.numeric.U256 (| + pow (| + base, + exponent, + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signextend : 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. + + *) + let* byte_num := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..6de26bb822 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/bitwise.v @@ -0,0 +1,156 @@ +(* +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 homestead.vm.gas. +Require homestead.vm.stack. + +Definition bitwise_and : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_or : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_xor : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_not : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition get_byte : 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. + + *) + let* byte_index := stack.pop (| + evm.["stack"] + |) in + let* word := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..2c8581802b --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/block.v @@ -0,0 +1,183 @@ +(* +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 homestead.vm.gas. +Require homestead.vm.stack. + +Definition block_hash : 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. + + *) + let* block_number := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOCK_HASH + |) in + let* max_block_number := (* TODO expression *) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + + +Definition coinbase : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["coinbase"] + |) + |) in + (* TODO statement *) + + +Definition timestamp : 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 (| + evm.["stack"], + evm.["env"].["time"] + |) in + (* TODO statement *) + + +Definition number : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["number"] + |) + |) in + (* TODO statement *) + + +Definition difficulty : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["difficulty"] + |) + |) in + (* TODO statement *) + + +Definition gas_limit : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_limit"] + |) + |) in + (* TODO statement *) + 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..3c0d9e716a --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/comparison.v @@ -0,0 +1,206 @@ +(* +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 homestead.vm.gas. +Require homestead.vm.stack. + +Definition less_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_less_than : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition greater_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_greater_than : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition equal : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition is_zero : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..8559f589ea --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/control_flow.v @@ -0,0 +1,156 @@ +(* +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 homestead.vm.gas. +Require homestead.vm.exceptions. +Require homestead.vm.stack. + +Definition stop : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition jump : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_MID + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition jumpi : 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. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* conditional_value := stack.pop (| + evm.["stack"] + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_HIGH + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition pc : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["pc"] + |) + |) in + (* TODO statement *) + + +Definition gas_left : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + + +Definition jumpdest : 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 *) + (* TODO statement *) + 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..b831ae9a31 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/environment.v @@ -0,0 +1,434 @@ +(* +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 homestead.state. +Require homestead.utils.address. +Require homestead.vm.memory. +Require homestead.vm.gas. +Require homestead.vm.stack. + +Definition address : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["current_target"] + |) + |) in + (* TODO statement *) + + +Definition balance : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BALANCE + |) in + let* balance := state.get_account (| + evm.["env"].["state"], + address + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition origin : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["origin"] + |) + |) in + (* TODO statement *) + + +Definition caller : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["caller"] + |) + |) in + (* TODO statement *) + + +Definition callvalue : 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 (| + evm.["stack"], + evm.["message"].["value"] + |) in + (* TODO statement *) + + +Definition calldataload : 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. + + *) + let* start_index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + start_index, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + value + |) + |) in + (* TODO statement *) + + +Definition calldatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["message"].["data"] + |) + |) + |) in + (* TODO statement *) + + +Definition calldatacopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* data_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + data_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition codesize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["code"] + |) + |) + |) in + (* TODO statement *) + + +Definition codecopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["code"], + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition gasprice : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_price"] + |) + |) in + (* TODO statement *) + + +Definition extcodesize : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_EXTERNAL + |) in + let* codesize := ethereum_types.numeric.U256 (| + len (| + state.get_account (| + evm.["env"].["state"], + address + |).["code"] + |) + |) in + do* stack.push (| + evm.["stack"], + codesize + |) in + (* TODO statement *) + + +Definition extcodecopy : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* code := state.get_account (| + evm.["env"].["state"], + address + |).["code"] in + let* value := vm.memory.buffer_read (| + code, + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + 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..593b441512 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/keccak.v @@ -0,0 +1,67 @@ +(* +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 homestead.vm.gas. +Require homestead.vm.memory. +Require homestead.vm.stack. + +Definition keccak : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* word_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + let* hash := ethereum.crypto.hash.keccak256 (| + data + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + 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..9da37966ec --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/log.v @@ -0,0 +1,59 @@ +(* +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 homestead.blocks. +Require homestead.vm.gas. +Require homestead.vm.memory. +Require homestead.vm.stack. + +Definition log_n : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* topics := (* TODO expression *) in + (* TODO statement *) + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* log_entry := blocks.Log (| + + |) in + (* TODO assignment *) + (* TODO statement *) + 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..1140586852 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/memory.v @@ -0,0 +1,158 @@ +(* +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 homestead.vm.gas. +Require homestead.vm.memory. +Require homestead.vm.stack. + +Definition mstore : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* memory.memory_write (| + evm.["memory"], + start_position, + value + |) in + (* TODO statement *) + + +Definition mstore8 : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + (* TODO expression *) + |) in + do* memory.memory_write (| + evm.["memory"], + start_position, + normalized_bytes_value + |) in + (* TODO statement *) + + +Definition mload : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.memory_read_bytes (| + evm.["memory"], + start_position, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition msize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["memory"] + |) + |) + |) in + (* TODO statement *) + 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..e73a536f4a --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/stack.v @@ -0,0 +1,133 @@ +(* +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 homestead.vm.exceptions. +Require homestead.vm.gas. +Require homestead.vm.memory. + +Definition pop : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* stack.["pop"] (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BASE + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition push_n : 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 + let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + evm.["code"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + num_bytes + |) + |) + |) in + do* stack.["push"] (| + evm.["stack"], + data_to_push + |) in + (* TODO statement *) + + +Definition dup_n : 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 *) + let* data_to_duplicate := (* TODO expression *) in + do* stack.["push"] (| + evm.["stack"], + data_to_duplicate + |) in + (* TODO statement *) + + +Definition swap_n : 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 *) + (* TODO statement *) + 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..dc3f8939a6 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/storage.v @@ -0,0 +1,88 @@ +(* +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 homestead.state. +Require homestead.vm.gas. +Require homestead.vm.stack. + +Definition sload : 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. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_SLOAD + |) in + let* value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition sstore : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + let* current_value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + do* state.set_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + 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..71d4317017 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/system.v @@ -0,0 +1,357 @@ +(* +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 homestead.fork_types. +Require homestead.state. +Require homestead.utils.address. +Require homestead.vm.gas. +Require homestead.vm.memory. +Require homestead.vm.stack. + +Definition create : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* create_message_gas := evm.["gas_left"] in + (* TODO assignment *) + (* TODO statement *) + let* sender_address := evm.["message"].["current_target"] in + let* sender := state.get_account (| + evm.["env"].["state"], + sender_address + |) in + let* contract_address := utils.address.compute_contract_address (| + evm.["message"].["current_target"], + state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["nonce"] + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition return_ : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + + +Definition generic_call : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_input_start_position, + memory_input_size + |) in + let* code := state.get_account (| + evm.["env"].["state"], + code_address + |).["code"] in + let* child_message := Message (| + + |) in + let* child_evm := process_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + let* actual_output_size := min (| + memory_output_size, + ethereum_types.numeric.U256 (| + len (| + child_evm.["output"] + |) + |) + |) in + do* memory.memory_write (| + evm.["memory"], + memory_output_start_position, + (* TODO expression *) + |) in + + +Definition call : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* message_call_gas := gas.calculate_message_call_gas (| + evm.["env"].["state"], + gas, + to, + value + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition callcode : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* to := evm.["message"].["current_target"] in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* message_call_gas := gas.calculate_message_call_gas (| + evm.["env"].["state"], + gas, + to, + value + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition selfdestruct : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* beneficiary := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* gas_cost := gas.GAS_ZERO in + let* originator := evm.["message"].["current_target"] in + let* refunded_accounts := evm.["accounts_to_delete"] in + let* parent_evm := evm.["message"].["parent_evm"] in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + let* beneficiary_balance := state.get_account (| + evm.["env"].["state"], + beneficiary + |).["balance"] in + let* originator_balance := state.get_account (| + evm.["env"].["state"], + originator + |).["balance"] in + do* state.set_account_balance (| + evm.["env"].["state"], + beneficiary, + (* TODO expression *) + |) in + do* state.set_account_balance (| + evm.["env"].["state"], + originator, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* evm.["accounts_to_delete"].["add"] (| + originator + |) in + (* TODO assignment *) + (* TODO statement *) + + +Definition delegatecall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + gas, + evm.["message"].["value"], + evm.["message"].["caller"], + evm.["message"].["current_target"], + code_address, + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + 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..fc1c693a21 --- /dev/null +++ b/coq/ethereum/homestead/vm/interpreter.v @@ -0,0 +1,151 @@ +(* +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 homestead.blocks. +Require homestead.fork_types. +Require homestead.state. +Require homestead.vm. +Require homestead.vm.gas. +Require homestead.vm.precompiled_contracts.mapping. +Require homestead.vm.exceptions. +Require homestead.vm.instructions. +Require homestead.vm.runtime. + +Definition process_message_call : M unit := + (* + 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 *) + let* tx_end := ethereum.trace.TransactionEnd (| + (* TODO expression *), + evm.["output"], + evm.["error"] + |) in + do* ethereum.trace.evm_trace (| + evm, + tx_end + |) in + (* TODO statement *) + + +Definition process_create_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.destroy_storage (| + env.["state"], + message.["current_target"] + |) in + let* evm := process_message (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.touch_account (| + env.["state"], + message.["current_target"] + |) in + (* TODO statement *) + let* evm := execute_code (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition execute_code : M unit := + (* + 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 + *) + let* code := message.["code"] in + let* valid_jump_destinations := runtime.get_valid_jump_destinations (| + code + |) in + let* evm := Evm (| + + |) in + (* TODO statement *) + (* TODO statement *) + 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..94b6a44639 --- /dev/null +++ b/coq/ethereum/homestead/vm/memory.v @@ -0,0 +1,75 @@ +(* +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 : 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 *) + + +Definition memory_read_bytes : M unit := + (* + 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 *) + + +Definition buffer_read : M unit := + (* + 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 *) + 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..88d5fdef55 --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/__init__.v @@ -0,0 +1,16 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require 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..546095c1ec --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,93 @@ +(* +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 homestead.vm. +Require homestead.vm.gas. +Require homestead.vm.memory. + +Definition ecrecover : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_ECRECOVER + |) in + let* message_hash_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* message_hash := ethereum.crypto.hash.Hash32 (| + message_hash_bytes + |) in + let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + address, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..92e3c9c09d --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/identity.v @@ -0,0 +1,36 @@ +(* +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 homestead.vm. +Require homestead.vm.gas. + +Definition identity : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..66be2c3300 --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/mapping.v @@ -0,0 +1,20 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require homestead.fork_types. +Require homestead.vm.precompiled_contracts.ecrecover. +Require homestead.vm.precompiled_contracts.identity. +Require homestead.vm.precompiled_contracts.ripemd160. +Require 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..bc5e73dd3c --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,42 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + let* hash_bytes := hashlib.["new"] (| + (* TODO expression *), + data + |).["digest"] (| + + |) in + let* padded_hash := left_pad_zero_bytes (| + hash_bytes, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..da6972d411 --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/sha256.v @@ -0,0 +1,32 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..422aa6768f --- /dev/null +++ b/coq/ethereum/homestead/vm/runtime.v @@ -0,0 +1,49 @@ +(* +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 homestead.vm.instructions. + +Definition get_valid_jump_destinations : M unit := + (* + 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. + *) + let* valid_jump_destinations := set (| + + |) in + let* pc := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..8ecce81148 --- /dev/null +++ b/coq/ethereum/homestead/vm/stack.v @@ -0,0 +1,53 @@ +(* +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 homestead.vm.exceptions. + +Definition pop : M unit := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + + +Definition push : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + 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..707b65b3e7 --- /dev/null +++ b/coq/ethereum/istanbul/__init__.v @@ -0,0 +1,7 @@ +(* +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..d31caca2a8 --- /dev/null +++ b/coq/ethereum/istanbul/blocks.v @@ -0,0 +1,19 @@ +(* +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 ..crypto.hash. +Require istanbul.fork_types. +Require 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..6daec8e931 --- /dev/null +++ b/coq/ethereum/istanbul/bloom.v @@ -0,0 +1,66 @@ +(* +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 istanbul.blocks. +Require istanbul.fork_types. + +Definition add_to_bloom : 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. + *) + let* hash := ethereum.crypto.hash.keccak256 (| + bloom_entry + |) in + (* TODO statement *) + + +Definition logs_bloom : M unit := + (* + 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 *) + 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..7cede29ef6 --- /dev/null +++ b/coq/ethereum/istanbul/fork.v @@ -0,0 +1,760 @@ +(* +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 istanbul.blocks. +Require istanbul.bloom. +Require istanbul.fork_types. +Require istanbul.state. +Require istanbul.transactions. +Require istanbul.trie. +Require istanbul.utils.message. +Require istanbul.vm.interpreter. + +Definition apply_fork : M unit := + (* + 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 *) + + +Definition get_last_256_block_hashes : M unit := + (* + 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. + *) + let* recent_blocks := (* TODO expression *) in + (* TODO statement *) + let* recent_block_hashes := (* TODO expression *) in + (* TODO statement *) + let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *).["header"] + |) + |) in + do* recent_block_hashes.["append"] (| + most_recent_block_hash + |) in + (* TODO statement *) + + +Definition state_transition : 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`. + *) + let* parent_header := (* TODO expression *).["header"] in + do* validate_header (| + block.["header"], + parent_header + |) in + do* validate_ommers (| + block.["ommers"], + block.["header"], + chain + |) in + let* apply_body_output := apply_body (| + chain.["state"], + get_last_256_block_hashes (| + chain + |), + block.["header"].["coinbase"], + block.["header"].["number"], + block.["header"].["gas_limit"], + block.["header"].["timestamp"], + block.["header"].["difficulty"], + block.["transactions"], + block.["ommers"], + chain.["chain_id"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* chain.["blocks"].["append"] (| + block + |) in + (* TODO statement *) + + +Definition validate_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 + *) + let* parent_has_ommers := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* block_difficulty := calculate_block_difficulty (| + header.["number"], + header.["timestamp"], + parent_header.["timestamp"], + parent_header.["difficulty"], + parent_has_ommers + |) in + (* TODO statement *) + let* block_parent_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + parent_header + |) + |) in + (* TODO statement *) + do* validate_proof_of_work (| + header + |) in + + +Definition generate_header_hash_for_pow : M unit := + (* + 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. + *) + let* header_data_without_pow_artefacts := (* TODO expression *) in + (* TODO statement *) + + +Definition validate_proof_of_work : 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. + *) + let* header_hash := generate_header_hash_for_pow (| + header + |) in + let* cache := ethereum.ethash.generate_cache (| + header.["number"] + |) in + (* TODO assignment *) + (* TODO statement *) + let* limit := (* TODO expression *) in + (* TODO statement *) + + +Definition check_transaction : M unit := + (* + 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 *) + let* sender_address := recover_sender (| + chain_id, + tx + |) in + (* TODO statement *) + + +Definition make_receipt : M unit := + (* + 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. + *) + let* receipt := blocks.Receipt (| + + |) in + (* TODO statement *) + + +Definition apply_body : M unit := + (* + 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. + *) + let* gas_available := block_gas_limit in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* pay_rewards (| + state, + block_number, + coinbase, + ommers + |) in + let* block_gas_used := (* TODO expression *) in + let* block_logs_bloom := bloom.logs_bloom (| + block_logs + |) in + (* TODO statement *) + + +Definition validate_ommers : 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. + *) + let* block_hash := rlp.["rlp_hash"] (| + block_header + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* ommers_hashes := (* TODO expression *) in + (* TODO statement *) + let* recent_canonical_blocks := (* TODO expression *) in + let* recent_canonical_block_hashes := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition pay_rewards : 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. + *) + let* ommer_count := ethereum_types.numeric.U256 (| + len (| + ommers + |) + |) in + let* miner_reward := (* TODO expression *) in + do* state.create_ether (| + state, + coinbase, + miner_reward + |) in + (* TODO statement *) + + +Definition process_transaction : M unit := + (* + 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 *) + let* sender := env.["origin"] in + let* sender_account := state.get_account (| + env.["state"], + sender + |) in + let* gas_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* gas := (* TODO expression *) in + do* state.increment_nonce (| + env.["state"], + sender + |) in + let* sender_balance_after_gas_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + ethereum_types.numeric.U256 (| + sender_balance_after_gas_fee + |) + |) in + let* message := utils.message.prepare_message (| + sender, + tx.["to"], + tx.["value"], + tx.["data"], + gas, + env + |) in + let* output := vm.interpreter.process_message_call (| + message, + env + |) in + let* gas_used := (* TODO expression *) in + let* gas_refund := min (| + (* TODO expression *), + ethereum_types.numeric.Uint (| + output.["refund_counter"] + |) + |) in + let* gas_refund_amount := (* TODO expression *) in + let* transaction_fee := (* TODO expression *) in + let* total_gas_used := (* TODO expression *) in + let* sender_balance_after_refund := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + sender_balance_after_refund + |) in + let* coinbase_balance_after_mining_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_transaction : M unit := + (* + 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 *) + + +Definition calculate_intrinsic_cost : M unit := + (* + 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. + *) + let* data_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition recover_sender : M unit := + (* + 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 *) + + +Definition signing_hash_pre155 : M unit := + (* + 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 *) + + +Definition signing_hash_155 : M unit := + (* + 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 *) + + +Definition compute_header_hash : M unit := + (* + 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 *) + + +Definition check_gas_limit : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_block_difficulty : M unit := + (* + 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. + *) + let* offset := (* TODO expression *) in + let* difficulty := (* TODO expression *) in + let* num_bomb_periods := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..14de99d5e5 --- /dev/null +++ b/coq/ethereum/istanbul/fork_types.v @@ -0,0 +1,29 @@ +(* +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 ..crypto.hash. + +Definition encode_account : M unit := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + 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..11071bec95 --- /dev/null +++ b/coq/ethereum/istanbul/state.v @@ -0,0 +1,593 @@ +(* +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 istanbul.fork_types. +Require istanbul.trie. + +Definition close_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 *) + + +Definition begin_transaction : 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* state.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + + +Definition commit_transaction : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* state.["_snapshots"].["pop"] (| + + |) in + (* TODO statement *) + + +Definition rollback_transaction : 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 *) + + +Definition get_account : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition get_account_optional : M unit := + (* + 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. + *) + let* account := trie.trie_get (| + state.["_main_trie"], + address + |) in + (* TODO statement *) + + +Definition set_account : 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 (| + state.["_main_trie"], + address, + account + |) in + + +Definition destroy_account : 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* destroy_storage (| + state, + address + |) in + do* set_account (| + state, + address, + (* TODO expression *) + |) in + + +Definition destroy_storage : 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 *) + + +Definition mark_account_created : 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* state.["created_accounts"].["add"] (| + address + |) in + + +Definition get_storage : M unit := + (* + 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. + *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_storage : 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 *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition storage_root : M unit := + (* + 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 *) + + +Definition state_root : M unit := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition account_exists : M unit := + (* + 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 *) + + +Definition account_has_code_or_nonce : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_empty : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition account_exists_and_is_empty : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_alive : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition modify_state : M unit := + (* + Modify an `Account` in the `State`. + *) + do* set_account (| + state, + address, + ethereum_types.frozen.modify (| + get_account (| + state, + address + |), + f + |) + |) in + + +Definition move_ether : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* modify_state (| + state, + sender_address, + reduce_sender_balance + |) in + do* modify_state (| + state, + recipient_address, + increase_recipient_balance + |) in + + +Definition set_account_balance : 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* modify_state (| + state, + address, + set_balance + |) in + + +Definition touch_account : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + + +Definition increment_nonce : 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* modify_state (| + state, + address, + increase_nonce + |) in + + +Definition set_code : 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* modify_state (| + state, + address, + write_code + |) in + + +Definition create_ether : 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* modify_state (| + state, + address, + increase_balance + |) in + + +Definition get_storage_original : M unit := + (* + 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 *) + let* original_account_trie := original_trie.["get"] (| + address + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + 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..85bf639bfb --- /dev/null +++ b/coq/ethereum/istanbul/transactions.v @@ -0,0 +1,12 @@ +(* +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 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..548de91e1c --- /dev/null +++ b/coq/ethereum/istanbul/trie.v @@ -0,0 +1,274 @@ +(* +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 : M unit := + (* + 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 *) + let* encoded := rlp.["encode"] (| + unencoded + |) in + (* TODO statement *) + + +Definition encode_node : M unit := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + + +Definition copy_trie : M unit := + (* + 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 *) + + +Definition trie_set : 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 *) + + +Definition trie_get : M unit := + (* + 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 *) + + +Definition common_prefix_length : M unit := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition nibble_list_to_compact : M unit := + (* + 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. + *) + let* compact := bytearray (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_nibble_list : M unit := + (* + 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. + *) + let* nibble_list := bytearray (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _prepare_trie : M unit := + (* + 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 *) + + +Definition root : M unit := + (* + 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. + *) + let* obj := _prepare_trie (| + trie, + get_storage_root + |) in + let* root_node := encode_internal_node (| + patricialize (| + obj, + Uint (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + + +Definition patricialize : M unit := + (* + 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 *) + let* arbitrary_key := next (| + iter (| + obj + |) + |) in + (* TODO statement *) + let* substring := (* TODO expression *) in + let* prefix_length := len (| + substring + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..beff4482b1 --- /dev/null +++ b/coq/ethereum/istanbul/utils/__init__.v @@ -0,0 +1,4 @@ +(* +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..4a42f362de --- /dev/null +++ b/coq/ethereum/istanbul/utils/address.v @@ -0,0 +1,99 @@ +(* +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 istanbul.fork_types. + +Definition to_address : M unit := + (* + 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 *) + + +Definition compute_contract_address : M unit := + (* + 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. + *) + let* computed_address := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *) + |) + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition compute_create2_contract_address : M unit := + (* + 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. + *) + let* preimage := (* TODO expression *) in + let* computed_address := ethereum.crypto.hash.keccak256 (| + preimage + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + 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..c4628f2d15 --- /dev/null +++ b/coq/ethereum/istanbul/utils/hexadecimal.v @@ -0,0 +1,68 @@ +(* +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 istanbul.fork_types. + +Definition hex_to_root : M unit := + (* + 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 *) + + +Definition hex_to_bloom : M unit := + (* + 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 *) + + +Definition hex_to_address : M unit := + (* + 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 *) + 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..a57a990418 --- /dev/null +++ b/coq/ethereum/istanbul/utils/message.v @@ -0,0 +1,59 @@ +(* +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 istanbul.fork_types. +Require istanbul.state. +Require istanbul.vm. +Require istanbul.utils.address. + +Definition prepare_message : M unit := + (* + 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 *) + 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..51466b0c1e --- /dev/null +++ b/coq/ethereum/istanbul/vm/__init__.v @@ -0,0 +1,63 @@ +(* +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 istanbul.blocks. +Require istanbul.fork_types. +Require istanbul.state. +Require istanbul.vm.precompiled_contracts. + +Definition incorporate_child_on_success : 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* evm.["accounts_to_delete"].["update"] (| + child_evm.["accounts_to_delete"] + |) in + do* evm.["touched_accounts"].["update"] (| + child_evm.["touched_accounts"] + |) in + (* TODO statement *) + + +Definition incorporate_child_on_error : 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 *) + (* TODO statement *) + 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..1784494410 --- /dev/null +++ b/coq/ethereum/istanbul/vm/exceptions.v @@ -0,0 +1,15 @@ +(* +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..fc4bea6483 --- /dev/null +++ b/coq/ethereum/istanbul/vm/gas.v @@ -0,0 +1,151 @@ +(* +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 istanbul.vm.exceptions. + +Definition charge_gas : 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 (| + int (| + amount + |) + |) + |) in + (* TODO statement *) + + +Definition calculate_memory_gas_cost : M unit := + (* + 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. + *) + let* size_in_words := (* TODO expression *) in + let* linear_cost := (* TODO expression *) in + let* quadratic_cost := (* TODO expression *) in + let* total_gas_cost := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_gas_extend_memory : M unit := + (* + 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` + *) + let* size_to_extend := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* to_be_paid := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* current_size := ethereum_types.numeric.Uint (| + len (| + memory + |) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_message_call_gas : M unit := + (* + 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` + *) + let* call_stipend := (* TODO expression *) in + (* TODO statement *) + let* gas := min (| + gas, + max_message_call_gas (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + + +Definition max_message_call_gas : M unit := + (* + 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 *) + 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..b36b1ebfef --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/__init__.v @@ -0,0 +1,15 @@ +(* +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..0de6949ccd --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/arithmetic.v @@ -0,0 +1,387 @@ +(* +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 istanbul.vm.gas. +Require istanbul.vm.stack. + +Definition add : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_add"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition sub : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_sub"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mul : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + let* result := x.["wrapping_mul"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition div : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |) in + let* divisor := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + quotient + |) in + (* TODO statement *) + + +Definition sdiv : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* divisor := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + quotient + |) + |) in + (* TODO statement *) + + +Definition mod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + remainder + |) in + (* TODO statement *) + + +Definition smod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* y := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + remainder + |) + |) in + (* TODO statement *) + + +Definition addmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mulmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition exp : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* base := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent_bits := exponent.["bit_length"] (| + + |) in + let* exponent_bytes := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* result := ethereum_types.numeric.U256 (| + pow (| + base, + exponent, + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signextend : 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. + + *) + let* byte_num := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..c62b7f7510 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/bitwise.v @@ -0,0 +1,245 @@ +(* +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 istanbul.vm.gas. +Require istanbul.vm.stack. + +Definition bitwise_and : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_or : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_xor : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_not : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition get_byte : 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. + + *) + let* byte_index := stack.pop (| + evm.["stack"] + |) in + let* word := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shl : 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. + *) + let* shift := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shr : 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. + *) + let* shift := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_sar : 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. + *) + let* shift := int (| + stack.pop (| + evm.["stack"] + |) + |) in + let* signed_value := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..cefae915dd --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/block.v @@ -0,0 +1,207 @@ +(* +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 istanbul.vm.gas. +Require istanbul.vm.stack. + +Definition block_hash : 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. + + *) + let* block_number := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOCK_HASH + |) in + let* max_block_number := (* TODO expression *) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + + +Definition coinbase : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["coinbase"] + |) + |) in + (* TODO statement *) + + +Definition timestamp : 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 (| + evm.["stack"], + evm.["env"].["time"] + |) in + (* TODO statement *) + + +Definition number : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["number"] + |) + |) in + (* TODO statement *) + + +Definition difficulty : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["difficulty"] + |) + |) in + (* TODO statement *) + + +Definition gas_limit : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_limit"] + |) + |) in + (* TODO statement *) + + +Definition chain_id : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["chain_id"] + |) + |) in + (* TODO statement *) + 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..965821babf --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/comparison.v @@ -0,0 +1,206 @@ +(* +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 istanbul.vm.gas. +Require istanbul.vm.stack. + +Definition less_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_less_than : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition greater_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_greater_than : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition equal : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition is_zero : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..109de0bba2 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/control_flow.v @@ -0,0 +1,156 @@ +(* +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 istanbul.vm.gas. +Require istanbul.vm.exceptions. +Require istanbul.vm.stack. + +Definition stop : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition jump : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_MID + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition jumpi : 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. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* conditional_value := stack.pop (| + evm.["stack"] + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_HIGH + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition pc : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["pc"] + |) + |) in + (* TODO statement *) + + +Definition gas_left : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + + +Definition jumpdest : 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 *) + (* TODO statement *) + 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..aa19a01e41 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/environment.v @@ -0,0 +1,556 @@ +(* +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 istanbul.fork_types. +Require istanbul.state. +Require istanbul.utils.address. +Require istanbul.vm.memory. +Require istanbul.vm.exceptions. +Require istanbul.vm.gas. +Require istanbul.vm.stack. + +Definition address : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["current_target"] + |) + |) in + (* TODO statement *) + + +Definition balance : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BALANCE + |) in + let* balance := state.get_account (| + evm.["env"].["state"], + address + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition origin : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["origin"] + |) + |) in + (* TODO statement *) + + +Definition caller : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["caller"] + |) + |) in + (* TODO statement *) + + +Definition callvalue : 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 (| + evm.["stack"], + evm.["message"].["value"] + |) in + (* TODO statement *) + + +Definition calldataload : 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. + + *) + let* start_index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + start_index, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + value + |) + |) in + (* TODO statement *) + + +Definition calldatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["message"].["data"] + |) + |) + |) in + (* TODO statement *) + + +Definition calldatacopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* data_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + data_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition codesize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["code"] + |) + |) + |) in + (* TODO statement *) + + +Definition codecopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["code"], + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition gasprice : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_price"] + |) + |) in + (* TODO statement *) + + +Definition extcodesize : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_EXTERNAL + |) in + let* codesize := ethereum_types.numeric.U256 (| + len (| + state.get_account (| + evm.["env"].["state"], + address + |).["code"] + |) + |) in + do* stack.push (| + evm.["stack"], + codesize + |) in + (* TODO statement *) + + +Definition extcodecopy : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* code := state.get_account (| + evm.["env"].["state"], + address + |).["code"] in + let* value := vm.memory.buffer_read (| + code, + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition returndatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["return_data"] + |) + |) + |) in + (* TODO statement *) + + +Definition returndatacopy : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* return_data_start_position := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition extcodehash : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_CODE_HASH + |) in + let* account := state.get_account (| + evm.["env"].["state"], + address + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + codehash + |) in + (* TODO statement *) + + +Definition self_balance : 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 + let* balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + 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..663bb54e6c --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/keccak.v @@ -0,0 +1,67 @@ +(* +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 istanbul.vm.gas. +Require istanbul.vm.memory. +Require istanbul.vm.stack. + +Definition keccak : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* word_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + let* hash := ethereum.crypto.hash.keccak256 (| + data + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + 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..6c9c08c1a5 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/log.v @@ -0,0 +1,61 @@ +(* +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 istanbul.blocks. +Require istanbul.vm.exceptions. +Require istanbul.vm.gas. +Require istanbul.vm.memory. +Require istanbul.vm.stack. + +Definition log_n : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* topics := (* TODO expression *) in + (* TODO statement *) + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* log_entry := blocks.Log (| + + |) in + (* TODO assignment *) + (* TODO statement *) + 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..5101da63be --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/memory.v @@ -0,0 +1,158 @@ +(* +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 istanbul.vm.gas. +Require istanbul.vm.memory. +Require istanbul.vm.stack. + +Definition mstore : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* memory.memory_write (| + evm.["memory"], + start_position, + value + |) in + (* TODO statement *) + + +Definition mstore8 : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + (* TODO expression *) + |) in + do* memory.memory_write (| + evm.["memory"], + start_position, + normalized_bytes_value + |) in + (* TODO statement *) + + +Definition mload : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.memory_read_bytes (| + evm.["memory"], + start_position, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition msize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["memory"] + |) + |) + |) in + (* TODO statement *) + 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..02257068ac --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/stack.v @@ -0,0 +1,133 @@ +(* +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 istanbul.vm.exceptions. +Require istanbul.vm.gas. +Require istanbul.vm.memory. + +Definition pop : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* stack.["pop"] (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BASE + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition push_n : 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 + let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + evm.["code"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + num_bytes + |) + |) + |) in + do* stack.["push"] (| + evm.["stack"], + data_to_push + |) in + (* TODO statement *) + + +Definition dup_n : 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 *) + let* data_to_duplicate := (* TODO expression *) in + do* stack.["push"] (| + evm.["stack"], + data_to_duplicate + |) in + (* TODO statement *) + + +Definition swap_n : 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 *) + (* TODO statement *) + 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..5d029d4e48 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/storage.v @@ -0,0 +1,96 @@ +(* +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 istanbul.state. +Require istanbul.vm.exceptions. +Require istanbul.vm.gas. +Require istanbul.vm.stack. + +Definition sload : 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. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_SLOAD + |) in + let* value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition sstore : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + (* TODO statement *) + let* original_value := state.get_storage_original (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + let* current_value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + do* state.set_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + 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..797d870b3d --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/system.v @@ -0,0 +1,581 @@ +(* +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 istanbul.fork_types. +Require istanbul.state. +Require istanbul.utils.address. +Require istanbul.vm.exceptions. +Require istanbul.vm.gas. +Require istanbul.vm.memory. +Require istanbul.vm.stack. + +Definition generic_create : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + let* create_message_gas := gas.max_message_call_gas (| + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + let* sender_address := evm.["message"].["current_target"] in + let* sender := state.get_account (| + evm.["env"].["state"], + sender_address + |) in + (* TODO statement *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) in + do* state.increment_nonce (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |) in + let* child_message := Message (| + + |) in + let* child_evm := process_create_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + + +Definition create : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_contract_address (| + evm.["message"].["current_target"], + state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["nonce"] + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size + |) in + (* TODO statement *) + + +Definition create2 : 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. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* salt := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* call_data_words := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_create2_contract_address (| + evm.["message"].["current_target"], + salt, + memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size + |) in + (* TODO statement *) + + +Definition return_ : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + + +Definition generic_call : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_input_start_position, + memory_input_size + |) in + let* code := state.get_account (| + evm.["env"].["state"], + code_address + |).["code"] in + let* child_message := Message (| + + |) in + let* child_evm := process_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + let* actual_output_size := min (| + memory_output_size, + ethereum_types.numeric.U256 (| + len (| + child_evm.["output"] + |) + |) + |) in + do* memory.memory_write (| + evm.["memory"], + memory_output_start_position, + (* TODO expression *) + |) in + + +Definition call : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* create_gas_cost := (* TODO expression *) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition callcode : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* to := evm.["message"].["current_target"] in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition selfdestruct : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* beneficiary := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* gas_cost := gas.GAS_SELF_DESTRUCT in + (* TODO statement *) + let* originator := evm.["message"].["current_target"] in + let* refunded_accounts := evm.["accounts_to_delete"] in + let* parent_evm := evm.["message"].["parent_evm"] in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + let* beneficiary_balance := state.get_account (| + evm.["env"].["state"], + beneficiary + |).["balance"] in + let* originator_balance := state.get_account (| + evm.["env"].["state"], + originator + |).["balance"] in + do* state.set_account_balance (| + evm.["env"].["state"], + beneficiary, + (* TODO expression *) + |) in + do* state.set_account_balance (| + evm.["env"].["state"], + originator, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* evm.["accounts_to_delete"].["add"] (| + originator + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition delegatecall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + gas.GAS_CALL + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + evm.["message"].["value"], + evm.["message"].["caller"], + evm.["message"].["current_target"], + code_address, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition staticcall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + gas.GAS_CALL + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + evm.["message"].["current_target"], + to, + to, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition revert : 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. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + extend_memory.["cost"] + |) in + (* TODO statement *) + let* output := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + 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..8c6b78f1fe --- /dev/null +++ b/coq/ethereum/istanbul/vm/interpreter.v @@ -0,0 +1,159 @@ +(* +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 istanbul.blocks. +Require istanbul.fork_types. +Require istanbul.state. +Require istanbul.vm. +Require istanbul.vm.gas. +Require istanbul.vm.precompiled_contracts.mapping. +Require istanbul.vm.exceptions. +Require istanbul.vm.instructions. +Require istanbul.vm.runtime. + +Definition process_message_call : M unit := + (* + 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 *) + let* tx_end := ethereum.trace.TransactionEnd (| + (* TODO expression *), + evm.["output"], + evm.["error"] + |) in + do* ethereum.trace.evm_trace (| + evm, + tx_end + |) in + (* TODO statement *) + + +Definition process_create_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.destroy_storage (| + env.["state"], + message.["current_target"] + |) in + do* state.mark_account_created (| + env.["state"], + message.["current_target"] + |) in + do* state.increment_nonce (| + env.["state"], + message.["current_target"] + |) in + let* evm := process_message (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.touch_account (| + env.["state"], + message.["current_target"] + |) in + (* TODO statement *) + let* evm := execute_code (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition execute_code : M unit := + (* + 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 + *) + let* code := message.["code"] in + let* valid_jump_destinations := runtime.get_valid_jump_destinations (| + code + |) in + let* evm := Evm (| + + |) in + (* TODO statement *) + (* TODO statement *) + 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..94b6a44639 --- /dev/null +++ b/coq/ethereum/istanbul/vm/memory.v @@ -0,0 +1,75 @@ +(* +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 : 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 *) + + +Definition memory_read_bytes : M unit := + (* + 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 *) + + +Definition buffer_read : M unit := + (* + 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 *) + 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..675a96d4e0 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/__init__.v @@ -0,0 +1,16 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require 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..3ba57da591 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,187 @@ +(* +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 istanbul.vm. +Require istanbul.vm.gas. +Require istanbul.vm.memory. +Require istanbul.vm.exceptions. + +Definition alt_bn128_add : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* x1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x1_bytes + |) + |) in + let* y1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y1_bytes + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := (* TODO expression *) in + (* TODO assignment *) + + +Definition alt_bn128_mul : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* n := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := p0.["mul_by"] (| + n + |) in + (* TODO assignment *) + + +Definition alt_bn128_pairing_check : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..93b1faba33 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,41 @@ +(* +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 istanbul.vm. +Require istanbul.vm.gas. +Require istanbul.vm.exceptions. + +Definition blake2f : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + (* TODO statement *) + let* blake2b := ethereum.crypto.blake2.Blake2b (| + + |) in + (* TODO assignment *) + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + 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..f435cce7e6 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,93 @@ +(* +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 istanbul.vm. +Require istanbul.vm.gas. +Require istanbul.vm.memory. + +Definition ecrecover : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_ECRECOVER + |) in + let* message_hash_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* message_hash := ethereum.crypto.hash.Hash32 (| + message_hash_bytes + |) in + let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + address, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..139cf73308 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/identity.v @@ -0,0 +1,36 @@ +(* +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 istanbul.vm. +Require istanbul.vm.gas. + +Definition identity : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..b99612c2e2 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/mapping.v @@ -0,0 +1,23 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require istanbul.fork_types. +Require istanbul.vm.precompiled_contracts.alt_bn128. +Require istanbul.vm.precompiled_contracts.blake2f. +Require istanbul.vm.precompiled_contracts.ecrecover. +Require istanbul.vm.precompiled_contracts.identity. +Require istanbul.vm.precompiled_contracts.modexp. +Require istanbul.vm.precompiled_contracts.ripemd160. +Require 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..ca0c8b470c --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/modexp.v @@ -0,0 +1,202 @@ +(* +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 istanbul.vm. +Require istanbul.vm.gas. +Require istanbul.vm.memory. + +Definition modexp : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + let* data := evm.["message"].["data"] in + let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_start := (* TODO expression *) in + let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + min (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + exp_length + |) + |) + |) in + do* vm.gas.charge_gas (| + evm, + gas_cost (| + base_length, + modulus_length, + exp_length, + exp_head + |) + |) in + (* TODO statement *) + let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + base_length + |) + |) in + let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + exp_length + |) + |) in + let* modulus_start := (* TODO expression *) in + let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + modulus_start, + modulus_length + |) + |) in + (* TODO statement *) + + +Definition complexity : M unit := + (* + 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. + *) + let* max_length := max (| + ethereum_types.numeric.Uint (| + base_length + |), + ethereum_types.numeric.Uint (| + modulus_length + |) + |) in + (* TODO statement *) + + +Definition iterations : M unit := + (* + 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 *) + + +Definition gas_cost : M unit := + (* + 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. + *) + let* multiplication_complexity := complexity (| + base_length, + modulus_length + |) in + let* iteration_count := iterations (| + exponent_length, + exponent_head + |) in + let* cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..bc5e73dd3c --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,42 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + let* hash_bytes := hashlib.["new"] (| + (* TODO expression *), + data + |).["digest"] (| + + |) in + let* padded_hash := left_pad_zero_bytes (| + hash_bytes, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..da6972d411 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/sha256.v @@ -0,0 +1,32 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..d13f6e9fbd --- /dev/null +++ b/coq/ethereum/istanbul/vm/runtime.v @@ -0,0 +1,49 @@ +(* +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 istanbul.vm.instructions. + +Definition get_valid_jump_destinations : M unit := + (* + 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. + *) + let* valid_jump_destinations := set (| + + |) in + let* pc := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..b545eac921 --- /dev/null +++ b/coq/ethereum/istanbul/vm/stack.v @@ -0,0 +1,53 @@ +(* +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 istanbul.vm.exceptions. + +Definition pop : M unit := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + + +Definition push : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + 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..d9b3a5d42b --- /dev/null +++ b/coq/ethereum/london/__init__.v @@ -0,0 +1,6 @@ +(* +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..c3a86f863d --- /dev/null +++ b/coq/ethereum/london/blocks.v @@ -0,0 +1,19 @@ +(* +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 ..crypto.hash. +Require london.fork_types. +Require 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..724ded2a41 --- /dev/null +++ b/coq/ethereum/london/bloom.v @@ -0,0 +1,66 @@ +(* +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 london.blocks. +Require london.fork_types. + +Definition add_to_bloom : 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. + *) + let* hash := ethereum.crypto.hash.keccak256 (| + bloom_entry + |) in + (* TODO statement *) + + +Definition logs_bloom : M unit := + (* + 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 *) + 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..137ea143f6 --- /dev/null +++ b/coq/ethereum/london/exceptions.v @@ -0,0 +1,6 @@ +(* +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..27d027a838 --- /dev/null +++ b/coq/ethereum/london/fork.v @@ -0,0 +1,843 @@ +(* +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 london.blocks. +Require london.bloom. +Require london.fork_types. +Require london.state. +Require london.transactions. +Require london.trie. +Require london.utils.message. +Require london.vm.interpreter. + +Definition apply_fork : M unit := + (* + 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 *) + + +Definition get_last_256_block_hashes : M unit := + (* + 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. + *) + let* recent_blocks := (* TODO expression *) in + (* TODO statement *) + let* recent_block_hashes := (* TODO expression *) in + (* TODO statement *) + let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *).["header"] + |) + |) in + do* recent_block_hashes.["append"] (| + most_recent_block_hash + |) in + (* TODO statement *) + + +Definition state_transition : 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`. + *) + let* parent_header := (* TODO expression *).["header"] in + do* validate_header (| + block.["header"], + parent_header + |) in + do* validate_ommers (| + block.["ommers"], + block.["header"], + chain + |) in + let* apply_body_output := apply_body (| + chain.["state"], + get_last_256_block_hashes (| + chain + |), + block.["header"].["coinbase"], + block.["header"].["number"], + block.["header"].["base_fee_per_gas"], + block.["header"].["gas_limit"], + block.["header"].["timestamp"], + block.["header"].["difficulty"], + block.["transactions"], + block.["ommers"], + chain.["chain_id"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* chain.["blocks"].["append"] (| + block + |) in + (* TODO statement *) + + +Definition calculate_base_fee_per_gas : M unit := + (* + 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. + *) + let* parent_gas_target := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_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 *) + let* expected_base_fee_per_gas := INITIAL_BASE_FEE in + (* TODO statement *) + (* TODO statement *) + let* parent_has_ommers := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* block_difficulty := calculate_block_difficulty (| + header.["number"], + header.["timestamp"], + parent_header.["timestamp"], + parent_header.["difficulty"], + parent_has_ommers + |) in + (* TODO statement *) + let* block_parent_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + parent_header + |) + |) in + (* TODO statement *) + do* validate_proof_of_work (| + header + |) in + + +Definition generate_header_hash_for_pow : M unit := + (* + 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. + *) + let* header_data_without_pow_artefacts := (* TODO expression *) in + (* TODO statement *) + + +Definition validate_proof_of_work : 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. + *) + let* header_hash := generate_header_hash_for_pow (| + header + |) in + let* cache := ethereum.ethash.generate_cache (| + header.["number"] + |) in + (* TODO assignment *) + (* TODO statement *) + let* limit := (* TODO expression *) in + (* TODO statement *) + + +Definition check_transaction : M unit := + (* + 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 *) + let* sender_address := recover_sender (| + chain_id, + tx + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition make_receipt : M unit := + (* + 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. + *) + let* receipt := blocks.Receipt (| + + |) in + (* TODO statement *) + + +Definition apply_body : M unit := + (* + 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. + *) + let* gas_available := block_gas_limit in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* pay_rewards (| + state, + block_number, + coinbase, + ommers + |) in + let* block_gas_used := (* TODO expression *) in + let* block_logs_bloom := bloom.logs_bloom (| + block_logs + |) in + (* TODO statement *) + + +Definition validate_ommers : 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. + *) + let* block_hash := rlp.["rlp_hash"] (| + block_header + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* ommers_hashes := (* TODO expression *) in + (* TODO statement *) + let* recent_canonical_blocks := (* TODO expression *) in + let* recent_canonical_block_hashes := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition pay_rewards : 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. + *) + let* ommer_count := ethereum_types.numeric.U256 (| + len (| + ommers + |) + |) in + let* miner_reward := (* TODO expression *) in + do* state.create_ether (| + state, + coinbase, + miner_reward + |) in + (* TODO statement *) + + +Definition process_transaction : M unit := + (* + 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 *) + let* sender := env.["origin"] in + let* sender_account := state.get_account (| + env.["state"], + sender + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* effective_gas_fee := (* TODO expression *) in + let* gas := (* TODO expression *) in + do* state.increment_nonce (| + env.["state"], + sender + |) in + let* sender_balance_after_gas_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + ethereum_types.numeric.U256 (| + sender_balance_after_gas_fee + |) + |) in + let* preaccessed_addresses := set (| + + |) in + let* preaccessed_storage_keys := set (| + + |) in + (* TODO statement *) + let* message := utils.message.prepare_message (| + sender, + tx.["to"], + tx.["value"], + tx.["data"], + gas, + env + |) in + let* output := vm.interpreter.process_message_call (| + message, + env + |) in + let* gas_used := (* TODO expression *) in + let* gas_refund := min (| + (* TODO expression *), + ethereum_types.numeric.Uint (| + output.["refund_counter"] + |) + |) in + let* gas_refund_amount := (* TODO expression *) in + let* priority_fee_per_gas := (* TODO expression *) in + let* transaction_fee := (* TODO expression *) in + let* total_gas_used := (* TODO expression *) in + let* sender_balance_after_refund := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + sender_balance_after_refund + |) in + let* coinbase_balance_after_mining_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_transaction : M unit := + (* + 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 *) + + +Definition calculate_intrinsic_cost : M unit := + (* + 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. + *) + let* data_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + let* access_list_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + + +Definition recover_sender : M unit := + (* + 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 *) + + +Definition signing_hash_pre155 : M unit := + (* + 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 *) + + +Definition signing_hash_155 : M unit := + (* + 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 *) + + +Definition signing_hash_2930 : M unit := + (* + 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 *) + + +Definition signing_hash_1559 : M unit := + (* + 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 *) + + +Definition compute_header_hash : M unit := + (* + 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 *) + + +Definition check_gas_limit : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_block_difficulty : M unit := + (* + 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. + *) + let* offset := (* TODO expression *) in + let* difficulty := (* TODO expression *) in + let* num_bomb_periods := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..14de99d5e5 --- /dev/null +++ b/coq/ethereum/london/fork_types.v @@ -0,0 +1,29 @@ +(* +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 ..crypto.hash. + +Definition encode_account : M unit := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + 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..007b01e85f --- /dev/null +++ b/coq/ethereum/london/state.v @@ -0,0 +1,593 @@ +(* +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 london.fork_types. +Require london.trie. + +Definition close_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 *) + + +Definition begin_transaction : 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* state.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + + +Definition commit_transaction : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* state.["_snapshots"].["pop"] (| + + |) in + (* TODO statement *) + + +Definition rollback_transaction : 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 *) + + +Definition get_account : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition get_account_optional : M unit := + (* + 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. + *) + let* account := trie.trie_get (| + state.["_main_trie"], + address + |) in + (* TODO statement *) + + +Definition set_account : 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 (| + state.["_main_trie"], + address, + account + |) in + + +Definition destroy_account : 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* destroy_storage (| + state, + address + |) in + do* set_account (| + state, + address, + (* TODO expression *) + |) in + + +Definition destroy_storage : 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 *) + + +Definition mark_account_created : 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* state.["created_accounts"].["add"] (| + address + |) in + + +Definition get_storage : M unit := + (* + 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. + *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_storage : 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 *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition storage_root : M unit := + (* + 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 *) + + +Definition state_root : M unit := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition account_exists : M unit := + (* + 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 *) + + +Definition account_has_code_or_nonce : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_empty : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition account_exists_and_is_empty : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_alive : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition modify_state : M unit := + (* + Modify an `Account` in the `State`. + *) + do* set_account (| + state, + address, + ethereum_types.frozen.modify (| + get_account (| + state, + address + |), + f + |) + |) in + + +Definition move_ether : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* modify_state (| + state, + sender_address, + reduce_sender_balance + |) in + do* modify_state (| + state, + recipient_address, + increase_recipient_balance + |) in + + +Definition set_account_balance : 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* modify_state (| + state, + address, + set_balance + |) in + + +Definition touch_account : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + + +Definition increment_nonce : 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* modify_state (| + state, + address, + increase_nonce + |) in + + +Definition set_code : 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* modify_state (| + state, + address, + write_code + |) in + + +Definition create_ether : 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* modify_state (| + state, + address, + increase_balance + |) in + + +Definition get_storage_original : M unit := + (* + 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 *) + let* original_account_trie := original_trie.["get"] (| + address + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + 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..8c84a4032a --- /dev/null +++ b/coq/ethereum/london/transactions.v @@ -0,0 +1,27 @@ +(* +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 london.exceptions. +Require london.fork_types. + +Definition encode_transaction : M unit := + (* + Encode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + + +Definition decode_transaction : M unit := + (* + Decode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + 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..548de91e1c --- /dev/null +++ b/coq/ethereum/london/trie.v @@ -0,0 +1,274 @@ +(* +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 : M unit := + (* + 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 *) + let* encoded := rlp.["encode"] (| + unencoded + |) in + (* TODO statement *) + + +Definition encode_node : M unit := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + + +Definition copy_trie : M unit := + (* + 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 *) + + +Definition trie_set : 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 *) + + +Definition trie_get : M unit := + (* + 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 *) + + +Definition common_prefix_length : M unit := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition nibble_list_to_compact : M unit := + (* + 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. + *) + let* compact := bytearray (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_nibble_list : M unit := + (* + 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. + *) + let* nibble_list := bytearray (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _prepare_trie : M unit := + (* + 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 *) + + +Definition root : M unit := + (* + 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. + *) + let* obj := _prepare_trie (| + trie, + get_storage_root + |) in + let* root_node := encode_internal_node (| + patricialize (| + obj, + Uint (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + + +Definition patricialize : M unit := + (* + 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 *) + let* arbitrary_key := next (| + iter (| + obj + |) + |) in + (* TODO statement *) + let* substring := (* TODO expression *) in + let* prefix_length := len (| + substring + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..beff4482b1 --- /dev/null +++ b/coq/ethereum/london/utils/__init__.v @@ -0,0 +1,4 @@ +(* +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..c250f51fe7 --- /dev/null +++ b/coq/ethereum/london/utils/address.v @@ -0,0 +1,99 @@ +(* +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 london.fork_types. + +Definition to_address : M unit := + (* + 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 *) + + +Definition compute_contract_address : M unit := + (* + 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. + *) + let* computed_address := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *) + |) + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition compute_create2_contract_address : M unit := + (* + 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. + *) + let* preimage := (* TODO expression *) in + let* computed_address := ethereum.crypto.hash.keccak256 (| + preimage + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + 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..d606b6a6db --- /dev/null +++ b/coq/ethereum/london/utils/hexadecimal.v @@ -0,0 +1,68 @@ +(* +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 london.fork_types. + +Definition hex_to_root : M unit := + (* + 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 *) + + +Definition hex_to_bloom : M unit := + (* + 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 *) + + +Definition hex_to_address : M unit := + (* + 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 *) + 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..feedd4deef --- /dev/null +++ b/coq/ethereum/london/utils/message.v @@ -0,0 +1,82 @@ +(* +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 london.fork_types. +Require london.state. +Require london.vm. +Require london.vm.precompiled_contracts.mapping. +Require london.utils.address. + +Definition prepare_message : M unit := + (* + 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 *) + let* accessed_addresses := set (| + + |) in + do* accessed_addresses.["add"] (| + current_target + |) in + do* accessed_addresses.["add"] (| + caller + |) in + do* accessed_addresses.["update"] (| + vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS.["keys"] (| + + |) + |) in + do* accessed_addresses.["update"] (| + preaccessed_addresses + |) in + (* TODO statement *) + 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..a97b0b379a --- /dev/null +++ b/coq/ethereum/london/vm/__init__.v @@ -0,0 +1,69 @@ +(* +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 london.blocks. +Require london.fork_types. +Require london.state. +Require london.vm.precompiled_contracts. + +Definition incorporate_child_on_success : 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* evm.["accounts_to_delete"].["update"] (| + child_evm.["accounts_to_delete"] + |) in + do* evm.["touched_accounts"].["update"] (| + child_evm.["touched_accounts"] + |) in + (* TODO statement *) + do* evm.["accessed_addresses"].["update"] (| + child_evm.["accessed_addresses"] + |) in + do* evm.["accessed_storage_keys"].["update"] (| + child_evm.["accessed_storage_keys"] + |) in + + +Definition incorporate_child_on_error : 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 *) + (* TODO statement *) + 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..1784494410 --- /dev/null +++ b/coq/ethereum/london/vm/exceptions.v @@ -0,0 +1,15 @@ +(* +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..50f82cfa20 --- /dev/null +++ b/coq/ethereum/london/vm/gas.v @@ -0,0 +1,151 @@ +(* +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 london.vm.exceptions. + +Definition charge_gas : 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 (| + int (| + amount + |) + |) + |) in + (* TODO statement *) + + +Definition calculate_memory_gas_cost : M unit := + (* + 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. + *) + let* size_in_words := (* TODO expression *) in + let* linear_cost := (* TODO expression *) in + let* quadratic_cost := (* TODO expression *) in + let* total_gas_cost := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_gas_extend_memory : M unit := + (* + 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` + *) + let* size_to_extend := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* to_be_paid := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* current_size := ethereum_types.numeric.Uint (| + len (| + memory + |) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_message_call_gas : M unit := + (* + 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` + *) + let* call_stipend := (* TODO expression *) in + (* TODO statement *) + let* gas := min (| + gas, + max_message_call_gas (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + + +Definition max_message_call_gas : M unit := + (* + 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 *) + 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..b36b1ebfef --- /dev/null +++ b/coq/ethereum/london/vm/instructions/__init__.v @@ -0,0 +1,15 @@ +(* +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..f0724740f9 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/arithmetic.v @@ -0,0 +1,387 @@ +(* +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 london.vm.gas. +Require london.vm.stack. + +Definition add : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_add"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition sub : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_sub"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mul : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + let* result := x.["wrapping_mul"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition div : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |) in + let* divisor := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + quotient + |) in + (* TODO statement *) + + +Definition sdiv : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* divisor := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + quotient + |) + |) in + (* TODO statement *) + + +Definition mod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + remainder + |) in + (* TODO statement *) + + +Definition smod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* y := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + remainder + |) + |) in + (* TODO statement *) + + +Definition addmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mulmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition exp : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* base := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent_bits := exponent.["bit_length"] (| + + |) in + let* exponent_bytes := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* result := ethereum_types.numeric.U256 (| + pow (| + base, + exponent, + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signextend : 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. + + *) + let* byte_num := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..dfc5f29532 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/bitwise.v @@ -0,0 +1,245 @@ +(* +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 london.vm.gas. +Require london.vm.stack. + +Definition bitwise_and : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_or : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_xor : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_not : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition get_byte : 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. + + *) + let* byte_index := stack.pop (| + evm.["stack"] + |) in + let* word := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shl : 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. + *) + let* shift := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shr : 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. + *) + let* shift := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_sar : 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. + *) + let* shift := int (| + stack.pop (| + evm.["stack"] + |) + |) in + let* signed_value := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..4906386fc4 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/block.v @@ -0,0 +1,207 @@ +(* +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 london.vm.gas. +Require london.vm.stack. + +Definition block_hash : 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. + + *) + let* block_number := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOCK_HASH + |) in + let* max_block_number := (* TODO expression *) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + + +Definition coinbase : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["coinbase"] + |) + |) in + (* TODO statement *) + + +Definition timestamp : 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 (| + evm.["stack"], + evm.["env"].["time"] + |) in + (* TODO statement *) + + +Definition number : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["number"] + |) + |) in + (* TODO statement *) + + +Definition difficulty : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["difficulty"] + |) + |) in + (* TODO statement *) + + +Definition gas_limit : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_limit"] + |) + |) in + (* TODO statement *) + + +Definition chain_id : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["chain_id"] + |) + |) in + (* TODO statement *) + 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..7d4dbaedc0 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/comparison.v @@ -0,0 +1,206 @@ +(* +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 london.vm.gas. +Require london.vm.stack. + +Definition less_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_less_than : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition greater_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_greater_than : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition equal : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition is_zero : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..50a0957f1d --- /dev/null +++ b/coq/ethereum/london/vm/instructions/control_flow.v @@ -0,0 +1,156 @@ +(* +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 london.vm.gas. +Require london.vm.exceptions. +Require london.vm.stack. + +Definition stop : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition jump : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_MID + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition jumpi : 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. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* conditional_value := stack.pop (| + evm.["stack"] + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_HIGH + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition pc : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["pc"] + |) + |) in + (* TODO statement *) + + +Definition gas_left : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + + +Definition jumpdest : 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 *) + (* TODO statement *) + 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..530a443045 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/environment.v @@ -0,0 +1,568 @@ +(* +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 london.fork_types. +Require london.state. +Require london.utils.address. +Require london.vm.memory. +Require london.vm.exceptions. +Require london.vm.gas. +Require london.vm.stack. + +Definition address : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["current_target"] + |) + |) in + (* TODO statement *) + + +Definition balance : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* balance := state.get_account (| + evm.["env"].["state"], + address + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition origin : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["origin"] + |) + |) in + (* TODO statement *) + + +Definition caller : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["caller"] + |) + |) in + (* TODO statement *) + + +Definition callvalue : 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 (| + evm.["stack"], + evm.["message"].["value"] + |) in + (* TODO statement *) + + +Definition calldataload : 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. + + *) + let* start_index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + start_index, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + value + |) + |) in + (* TODO statement *) + + +Definition calldatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["message"].["data"] + |) + |) + |) in + (* TODO statement *) + + +Definition calldatacopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* data_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + data_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition codesize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["code"] + |) + |) + |) in + (* TODO statement *) + + +Definition codecopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["code"], + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition gasprice : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_price"] + |) + |) in + (* TODO statement *) + + +Definition extcodesize : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* codesize := ethereum_types.numeric.U256 (| + len (| + state.get_account (| + evm.["env"].["state"], + address + |).["code"] + |) + |) in + do* stack.push (| + evm.["stack"], + codesize + |) in + (* TODO statement *) + + +Definition extcodecopy : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* code := state.get_account (| + evm.["env"].["state"], + address + |).["code"] in + let* value := vm.memory.buffer_read (| + code, + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition returndatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["return_data"] + |) + |) + |) in + (* TODO statement *) + + +Definition returndatacopy : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* return_data_start_position := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition extcodehash : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* account := state.get_account (| + evm.["env"].["state"], + address + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + codehash + |) in + (* TODO statement *) + + +Definition self_balance : 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 + let* balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition base_fee : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["base_fee_per_gas"] + |) + |) in + (* TODO statement *) + 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..1a59188d7c --- /dev/null +++ b/coq/ethereum/london/vm/instructions/keccak.v @@ -0,0 +1,67 @@ +(* +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 london.vm.gas. +Require london.vm.memory. +Require london.vm.stack. + +Definition keccak : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* word_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + let* hash := ethereum.crypto.hash.keccak256 (| + data + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + 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..71e198ec76 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/log.v @@ -0,0 +1,61 @@ +(* +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 london.blocks. +Require london.vm.exceptions. +Require london.vm.gas. +Require london.vm.memory. +Require london.vm.stack. + +Definition log_n : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* topics := (* TODO expression *) in + (* TODO statement *) + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* log_entry := blocks.Log (| + + |) in + (* TODO assignment *) + (* TODO statement *) + 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..f3b36dd756 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/memory.v @@ -0,0 +1,158 @@ +(* +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 london.vm.gas. +Require london.vm.memory. +Require london.vm.stack. + +Definition mstore : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* memory.memory_write (| + evm.["memory"], + start_position, + value + |) in + (* TODO statement *) + + +Definition mstore8 : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + (* TODO expression *) + |) in + do* memory.memory_write (| + evm.["memory"], + start_position, + normalized_bytes_value + |) in + (* TODO statement *) + + +Definition mload : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.memory_read_bytes (| + evm.["memory"], + start_position, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition msize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["memory"] + |) + |) + |) in + (* TODO statement *) + 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..ea6ac0ddc8 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/stack.v @@ -0,0 +1,133 @@ +(* +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 london.vm.exceptions. +Require london.vm.gas. +Require london.vm.memory. + +Definition pop : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* stack.["pop"] (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BASE + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition push_n : 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 + let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + evm.["code"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + num_bytes + |) + |) + |) in + do* stack.["push"] (| + evm.["stack"], + data_to_push + |) in + (* TODO statement *) + + +Definition dup_n : 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 *) + let* data_to_duplicate := (* TODO expression *) in + do* stack.["push"] (| + evm.["stack"], + data_to_duplicate + |) in + (* TODO statement *) + + +Definition swap_n : 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 *) + (* TODO statement *) + 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..ca5c047075 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/storage.v @@ -0,0 +1,97 @@ +(* +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 london.state. +Require london.vm.exceptions. +Require london.vm.gas. +Require london.vm.stack. + +Definition sload : 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. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + (* TODO statement *) + let* value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition sstore : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + (* TODO statement *) + let* original_value := state.get_storage_original (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + let* current_value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + let* gas_cost := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + do* state.set_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + 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..cf16568388 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/system.v @@ -0,0 +1,585 @@ +(* +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 london.fork_types. +Require london.state. +Require london.utils.address. +Require london.vm.exceptions. +Require london.vm.gas. +Require london.vm.memory. +Require london.vm.stack. + +Definition generic_create : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + do* evm.["accessed_addresses"].["add"] (| + contract_address + |) in + let* create_message_gas := gas.max_message_call_gas (| + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + let* sender_address := evm.["message"].["current_target"] in + let* sender := state.get_account (| + evm.["env"].["state"], + sender_address + |) in + (* TODO statement *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) in + do* state.increment_nonce (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |) in + let* child_message := Message (| + + |) in + let* child_evm := process_create_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + + +Definition create : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_contract_address (| + evm.["message"].["current_target"], + state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["nonce"] + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size + |) in + (* TODO statement *) + + +Definition create2 : 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. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* salt := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* call_data_words := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_create2_contract_address (| + evm.["message"].["current_target"], + salt, + memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size + |) in + (* TODO statement *) + + +Definition return_ : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + + +Definition generic_call : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_input_start_position, + memory_input_size + |) in + let* code := state.get_account (| + evm.["env"].["state"], + code_address + |).["code"] in + let* child_message := Message (| + + |) in + let* child_evm := process_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + let* actual_output_size := min (| + memory_output_size, + ethereum_types.numeric.U256 (| + len (| + child_evm.["output"] + |) + |) + |) in + do* memory.memory_write (| + evm.["memory"], + memory_output_start_position, + (* TODO expression *) + |) in + + +Definition call : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* create_gas_cost := (* TODO expression *) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition callcode : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* to := evm.["message"].["current_target"] in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition selfdestruct : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* beneficiary := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* gas_cost := gas.GAS_SELF_DESTRUCT in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + let* originator := evm.["message"].["current_target"] in + let* beneficiary_balance := state.get_account (| + evm.["env"].["state"], + beneficiary + |).["balance"] in + let* originator_balance := state.get_account (| + evm.["env"].["state"], + originator + |).["balance"] in + do* state.set_account_balance (| + evm.["env"].["state"], + beneficiary, + (* TODO expression *) + |) in + do* state.set_account_balance (| + evm.["env"].["state"], + originator, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* evm.["accounts_to_delete"].["add"] (| + originator + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition delegatecall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + access_gas_cost + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + evm.["message"].["value"], + evm.["message"].["caller"], + evm.["message"].["current_target"], + code_address, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition staticcall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + access_gas_cost + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + evm.["message"].["current_target"], + to, + to, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition revert : 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. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + extend_memory.["cost"] + |) in + (* TODO statement *) + let* output := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + 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..4774a023e4 --- /dev/null +++ b/coq/ethereum/london/vm/interpreter.v @@ -0,0 +1,159 @@ +(* +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 london.blocks. +Require london.fork_types. +Require london.state. +Require london.vm. +Require london.vm.gas. +Require london.vm.precompiled_contracts.mapping. +Require london.vm.exceptions. +Require london.vm.instructions. +Require london.vm.runtime. + +Definition process_message_call : M unit := + (* + 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 *) + let* tx_end := ethereum.trace.TransactionEnd (| + (* TODO expression *), + evm.["output"], + evm.["error"] + |) in + do* ethereum.trace.evm_trace (| + evm, + tx_end + |) in + (* TODO statement *) + + +Definition process_create_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.destroy_storage (| + env.["state"], + message.["current_target"] + |) in + do* state.mark_account_created (| + env.["state"], + message.["current_target"] + |) in + do* state.increment_nonce (| + env.["state"], + message.["current_target"] + |) in + let* evm := process_message (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.touch_account (| + env.["state"], + message.["current_target"] + |) in + (* TODO statement *) + let* evm := execute_code (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition execute_code : M unit := + (* + 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 + *) + let* code := message.["code"] in + let* valid_jump_destinations := runtime.get_valid_jump_destinations (| + code + |) in + let* evm := Evm (| + + |) in + (* TODO statement *) + (* TODO statement *) + 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..94b6a44639 --- /dev/null +++ b/coq/ethereum/london/vm/memory.v @@ -0,0 +1,75 @@ +(* +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 : 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 *) + + +Definition memory_read_bytes : M unit := + (* + 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 *) + + +Definition buffer_read : M unit := + (* + 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 *) + 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..be64961fbf --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/__init__.v @@ -0,0 +1,16 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require 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..611de09a3e --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,187 @@ +(* +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 london.vm. +Require london.vm.gas. +Require london.vm.memory. +Require london.vm.exceptions. + +Definition alt_bn128_add : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* x1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x1_bytes + |) + |) in + let* y1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y1_bytes + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := (* TODO expression *) in + (* TODO assignment *) + + +Definition alt_bn128_mul : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* n := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := p0.["mul_by"] (| + n + |) in + (* TODO assignment *) + + +Definition alt_bn128_pairing_check : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..ac32ffbf50 --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,41 @@ +(* +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 london.vm. +Require london.vm.gas. +Require london.vm.exceptions. + +Definition blake2f : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + (* TODO statement *) + let* blake2b := ethereum.crypto.blake2.Blake2b (| + + |) in + (* TODO assignment *) + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + 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..319f0c80a6 --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,93 @@ +(* +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 london.vm. +Require london.vm.gas. +Require london.vm.memory. + +Definition ecrecover : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_ECRECOVER + |) in + let* message_hash_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* message_hash := ethereum.crypto.hash.Hash32 (| + message_hash_bytes + |) in + let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + address, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..553b8203e8 --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/identity.v @@ -0,0 +1,36 @@ +(* +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 london.vm. +Require london.vm.gas. + +Definition identity : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..19fbe5b55f --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/mapping.v @@ -0,0 +1,23 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require london.fork_types. +Require london.vm.precompiled_contracts.alt_bn128. +Require london.vm.precompiled_contracts.blake2f. +Require london.vm.precompiled_contracts.ecrecover. +Require london.vm.precompiled_contracts.identity. +Require london.vm.precompiled_contracts.modexp. +Require london.vm.precompiled_contracts.ripemd160. +Require 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..2773a521e4 --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/modexp.v @@ -0,0 +1,203 @@ +(* +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 london.vm. +Require london.vm.gas. +Require london.vm.memory. + +Definition modexp : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + let* data := evm.["message"].["data"] in + let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_start := (* TODO expression *) in + let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + min (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + exp_length + |) + |) + |) in + do* vm.gas.charge_gas (| + evm, + gas_cost (| + base_length, + modulus_length, + exp_length, + exp_head + |) + |) in + (* TODO statement *) + let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + base_length + |) + |) in + let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + exp_length + |) + |) in + let* modulus_start := (* TODO expression *) in + let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + modulus_start, + modulus_length + |) + |) in + (* TODO statement *) + + +Definition complexity : M unit := + (* + 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. + *) + let* max_length := max (| + ethereum_types.numeric.Uint (| + base_length + |), + ethereum_types.numeric.Uint (| + modulus_length + |) + |) in + let* words := (* TODO expression *) in + (* TODO statement *) + + +Definition iterations : M unit := + (* + 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 *) + + +Definition gas_cost : M unit := + (* + 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. + *) + let* multiplication_complexity := complexity (| + base_length, + modulus_length + |) in + let* iteration_count := iterations (| + exponent_length, + exponent_head + |) in + let* cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..bc5e73dd3c --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,42 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + let* hash_bytes := hashlib.["new"] (| + (* TODO expression *), + data + |).["digest"] (| + + |) in + let* padded_hash := left_pad_zero_bytes (| + hash_bytes, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..da6972d411 --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/sha256.v @@ -0,0 +1,32 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..5045bead7a --- /dev/null +++ b/coq/ethereum/london/vm/runtime.v @@ -0,0 +1,49 @@ +(* +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 london.vm.instructions. + +Definition get_valid_jump_destinations : M unit := + (* + 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. + *) + let* valid_jump_destinations := set (| + + |) in + let* pc := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..497e3e882e --- /dev/null +++ b/coq/ethereum/london/vm/stack.v @@ -0,0 +1,53 @@ +(* +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 london.vm.exceptions. + +Definition pop : M unit := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + + +Definition push : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + 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..e38f98952a --- /dev/null +++ b/coq/ethereum/muir_glacier/__init__.v @@ -0,0 +1,6 @@ +(* +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..9109c50849 --- /dev/null +++ b/coq/ethereum/muir_glacier/blocks.v @@ -0,0 +1,19 @@ +(* +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 ..crypto.hash. +Require muir_glacier.fork_types. +Require 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..b1702993bc --- /dev/null +++ b/coq/ethereum/muir_glacier/bloom.v @@ -0,0 +1,66 @@ +(* +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 muir_glacier.blocks. +Require muir_glacier.fork_types. + +Definition add_to_bloom : 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. + *) + let* hash := ethereum.crypto.hash.keccak256 (| + bloom_entry + |) in + (* TODO statement *) + + +Definition logs_bloom : M unit := + (* + 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 *) + 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..0a62c46841 --- /dev/null +++ b/coq/ethereum/muir_glacier/fork.v @@ -0,0 +1,760 @@ +(* +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 muir_glacier.blocks. +Require muir_glacier.bloom. +Require muir_glacier.fork_types. +Require muir_glacier.state. +Require muir_glacier.transactions. +Require muir_glacier.trie. +Require muir_glacier.utils.message. +Require muir_glacier.vm.interpreter. + +Definition apply_fork : M unit := + (* + 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 *) + + +Definition get_last_256_block_hashes : M unit := + (* + 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. + *) + let* recent_blocks := (* TODO expression *) in + (* TODO statement *) + let* recent_block_hashes := (* TODO expression *) in + (* TODO statement *) + let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *).["header"] + |) + |) in + do* recent_block_hashes.["append"] (| + most_recent_block_hash + |) in + (* TODO statement *) + + +Definition state_transition : 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`. + *) + let* parent_header := (* TODO expression *).["header"] in + do* validate_header (| + block.["header"], + parent_header + |) in + do* validate_ommers (| + block.["ommers"], + block.["header"], + chain + |) in + let* apply_body_output := apply_body (| + chain.["state"], + get_last_256_block_hashes (| + chain + |), + block.["header"].["coinbase"], + block.["header"].["number"], + block.["header"].["gas_limit"], + block.["header"].["timestamp"], + block.["header"].["difficulty"], + block.["transactions"], + block.["ommers"], + chain.["chain_id"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* chain.["blocks"].["append"] (| + block + |) in + (* TODO statement *) + + +Definition validate_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 + *) + let* parent_has_ommers := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* block_difficulty := calculate_block_difficulty (| + header.["number"], + header.["timestamp"], + parent_header.["timestamp"], + parent_header.["difficulty"], + parent_has_ommers + |) in + (* TODO statement *) + let* block_parent_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + parent_header + |) + |) in + (* TODO statement *) + do* validate_proof_of_work (| + header + |) in + + +Definition generate_header_hash_for_pow : M unit := + (* + 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. + *) + let* header_data_without_pow_artefacts := (* TODO expression *) in + (* TODO statement *) + + +Definition validate_proof_of_work : 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. + *) + let* header_hash := generate_header_hash_for_pow (| + header + |) in + let* cache := ethereum.ethash.generate_cache (| + header.["number"] + |) in + (* TODO assignment *) + (* TODO statement *) + let* limit := (* TODO expression *) in + (* TODO statement *) + + +Definition check_transaction : M unit := + (* + 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 *) + let* sender_address := recover_sender (| + chain_id, + tx + |) in + (* TODO statement *) + + +Definition make_receipt : M unit := + (* + 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. + *) + let* receipt := blocks.Receipt (| + + |) in + (* TODO statement *) + + +Definition apply_body : M unit := + (* + 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. + *) + let* gas_available := block_gas_limit in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* pay_rewards (| + state, + block_number, + coinbase, + ommers + |) in + let* block_gas_used := (* TODO expression *) in + let* block_logs_bloom := bloom.logs_bloom (| + block_logs + |) in + (* TODO statement *) + + +Definition validate_ommers : 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. + *) + let* block_hash := rlp.["rlp_hash"] (| + block_header + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* ommers_hashes := (* TODO expression *) in + (* TODO statement *) + let* recent_canonical_blocks := (* TODO expression *) in + let* recent_canonical_block_hashes := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition pay_rewards : 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. + *) + let* ommer_count := ethereum_types.numeric.U256 (| + len (| + ommers + |) + |) in + let* miner_reward := (* TODO expression *) in + do* state.create_ether (| + state, + coinbase, + miner_reward + |) in + (* TODO statement *) + + +Definition process_transaction : M unit := + (* + 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 *) + let* sender := env.["origin"] in + let* sender_account := state.get_account (| + env.["state"], + sender + |) in + let* gas_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* gas := (* TODO expression *) in + do* state.increment_nonce (| + env.["state"], + sender + |) in + let* sender_balance_after_gas_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + ethereum_types.numeric.U256 (| + sender_balance_after_gas_fee + |) + |) in + let* message := utils.message.prepare_message (| + sender, + tx.["to"], + tx.["value"], + tx.["data"], + gas, + env + |) in + let* output := vm.interpreter.process_message_call (| + message, + env + |) in + let* gas_used := (* TODO expression *) in + let* gas_refund := min (| + (* TODO expression *), + ethereum_types.numeric.Uint (| + output.["refund_counter"] + |) + |) in + let* gas_refund_amount := (* TODO expression *) in + let* transaction_fee := (* TODO expression *) in + let* total_gas_used := (* TODO expression *) in + let* sender_balance_after_refund := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + sender_balance_after_refund + |) in + let* coinbase_balance_after_mining_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_transaction : M unit := + (* + 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 *) + + +Definition calculate_intrinsic_cost : M unit := + (* + 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. + *) + let* data_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition recover_sender : M unit := + (* + 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 *) + + +Definition signing_hash_pre155 : M unit := + (* + 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 *) + + +Definition signing_hash_155 : M unit := + (* + 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 *) + + +Definition compute_header_hash : M unit := + (* + 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 *) + + +Definition check_gas_limit : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_block_difficulty : M unit := + (* + 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. + *) + let* offset := (* TODO expression *) in + let* difficulty := (* TODO expression *) in + let* num_bomb_periods := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..14de99d5e5 --- /dev/null +++ b/coq/ethereum/muir_glacier/fork_types.v @@ -0,0 +1,29 @@ +(* +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 ..crypto.hash. + +Definition encode_account : M unit := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + 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..8bd502c188 --- /dev/null +++ b/coq/ethereum/muir_glacier/state.v @@ -0,0 +1,593 @@ +(* +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 muir_glacier.fork_types. +Require muir_glacier.trie. + +Definition close_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 *) + + +Definition begin_transaction : 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* state.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + + +Definition commit_transaction : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* state.["_snapshots"].["pop"] (| + + |) in + (* TODO statement *) + + +Definition rollback_transaction : 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 *) + + +Definition get_account : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition get_account_optional : M unit := + (* + 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. + *) + let* account := trie.trie_get (| + state.["_main_trie"], + address + |) in + (* TODO statement *) + + +Definition set_account : 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 (| + state.["_main_trie"], + address, + account + |) in + + +Definition destroy_account : 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* destroy_storage (| + state, + address + |) in + do* set_account (| + state, + address, + (* TODO expression *) + |) in + + +Definition destroy_storage : 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 *) + + +Definition mark_account_created : 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* state.["created_accounts"].["add"] (| + address + |) in + + +Definition get_storage : M unit := + (* + 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. + *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_storage : 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 *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition storage_root : M unit := + (* + 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 *) + + +Definition state_root : M unit := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition account_exists : M unit := + (* + 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 *) + + +Definition account_has_code_or_nonce : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_empty : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition account_exists_and_is_empty : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_alive : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition modify_state : M unit := + (* + Modify an `Account` in the `State`. + *) + do* set_account (| + state, + address, + ethereum_types.frozen.modify (| + get_account (| + state, + address + |), + f + |) + |) in + + +Definition move_ether : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* modify_state (| + state, + sender_address, + reduce_sender_balance + |) in + do* modify_state (| + state, + recipient_address, + increase_recipient_balance + |) in + + +Definition set_account_balance : 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* modify_state (| + state, + address, + set_balance + |) in + + +Definition touch_account : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + + +Definition increment_nonce : 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* modify_state (| + state, + address, + increase_nonce + |) in + + +Definition set_code : 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* modify_state (| + state, + address, + write_code + |) in + + +Definition create_ether : 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* modify_state (| + state, + address, + increase_balance + |) in + + +Definition get_storage_original : M unit := + (* + 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 *) + let* original_account_trie := original_trie.["get"] (| + address + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + 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..27338180fa --- /dev/null +++ b/coq/ethereum/muir_glacier/transactions.v @@ -0,0 +1,12 @@ +(* +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 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..548de91e1c --- /dev/null +++ b/coq/ethereum/muir_glacier/trie.v @@ -0,0 +1,274 @@ +(* +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 : M unit := + (* + 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 *) + let* encoded := rlp.["encode"] (| + unencoded + |) in + (* TODO statement *) + + +Definition encode_node : M unit := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + + +Definition copy_trie : M unit := + (* + 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 *) + + +Definition trie_set : 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 *) + + +Definition trie_get : M unit := + (* + 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 *) + + +Definition common_prefix_length : M unit := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition nibble_list_to_compact : M unit := + (* + 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. + *) + let* compact := bytearray (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_nibble_list : M unit := + (* + 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. + *) + let* nibble_list := bytearray (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _prepare_trie : M unit := + (* + 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 *) + + +Definition root : M unit := + (* + 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. + *) + let* obj := _prepare_trie (| + trie, + get_storage_root + |) in + let* root_node := encode_internal_node (| + patricialize (| + obj, + Uint (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + + +Definition patricialize : M unit := + (* + 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 *) + let* arbitrary_key := next (| + iter (| + obj + |) + |) in + (* TODO statement *) + let* substring := (* TODO expression *) in + let* prefix_length := len (| + substring + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..beff4482b1 --- /dev/null +++ b/coq/ethereum/muir_glacier/utils/__init__.v @@ -0,0 +1,4 @@ +(* +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..18b2738fb9 --- /dev/null +++ b/coq/ethereum/muir_glacier/utils/address.v @@ -0,0 +1,99 @@ +(* +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 muir_glacier.fork_types. + +Definition to_address : M unit := + (* + 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 *) + + +Definition compute_contract_address : M unit := + (* + 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. + *) + let* computed_address := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *) + |) + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition compute_create2_contract_address : M unit := + (* + 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. + *) + let* preimage := (* TODO expression *) in + let* computed_address := ethereum.crypto.hash.keccak256 (| + preimage + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + 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..01dca945a4 --- /dev/null +++ b/coq/ethereum/muir_glacier/utils/hexadecimal.v @@ -0,0 +1,68 @@ +(* +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 muir_glacier.fork_types. + +Definition hex_to_root : M unit := + (* + 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 *) + + +Definition hex_to_bloom : M unit := + (* + 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 *) + + +Definition hex_to_address : M unit := + (* + 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 *) + 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..d32294a5cf --- /dev/null +++ b/coq/ethereum/muir_glacier/utils/message.v @@ -0,0 +1,59 @@ +(* +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 muir_glacier.fork_types. +Require muir_glacier.state. +Require muir_glacier.vm. +Require muir_glacier.utils.address. + +Definition prepare_message : M unit := + (* + 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 *) + 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..6adf91df71 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/__init__.v @@ -0,0 +1,63 @@ +(* +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 muir_glacier.blocks. +Require muir_glacier.fork_types. +Require muir_glacier.state. +Require muir_glacier.vm.precompiled_contracts. + +Definition incorporate_child_on_success : 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* evm.["accounts_to_delete"].["update"] (| + child_evm.["accounts_to_delete"] + |) in + do* evm.["touched_accounts"].["update"] (| + child_evm.["touched_accounts"] + |) in + (* TODO statement *) + + +Definition incorporate_child_on_error : 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 *) + (* TODO statement *) + 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..1784494410 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/exceptions.v @@ -0,0 +1,15 @@ +(* +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..03239a67ff --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/gas.v @@ -0,0 +1,151 @@ +(* +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 muir_glacier.vm.exceptions. + +Definition charge_gas : 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 (| + int (| + amount + |) + |) + |) in + (* TODO statement *) + + +Definition calculate_memory_gas_cost : M unit := + (* + 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. + *) + let* size_in_words := (* TODO expression *) in + let* linear_cost := (* TODO expression *) in + let* quadratic_cost := (* TODO expression *) in + let* total_gas_cost := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_gas_extend_memory : M unit := + (* + 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` + *) + let* size_to_extend := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* to_be_paid := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* current_size := ethereum_types.numeric.Uint (| + len (| + memory + |) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_message_call_gas : M unit := + (* + 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` + *) + let* call_stipend := (* TODO expression *) in + (* TODO statement *) + let* gas := min (| + gas, + max_message_call_gas (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + + +Definition max_message_call_gas : M unit := + (* + 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 *) + 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..b36b1ebfef --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/__init__.v @@ -0,0 +1,15 @@ +(* +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..21be74ba18 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/arithmetic.v @@ -0,0 +1,387 @@ +(* +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 muir_glacier.vm.gas. +Require muir_glacier.vm.stack. + +Definition add : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_add"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition sub : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_sub"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mul : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + let* result := x.["wrapping_mul"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition div : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |) in + let* divisor := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + quotient + |) in + (* TODO statement *) + + +Definition sdiv : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* divisor := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + quotient + |) + |) in + (* TODO statement *) + + +Definition mod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + remainder + |) in + (* TODO statement *) + + +Definition smod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* y := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + remainder + |) + |) in + (* TODO statement *) + + +Definition addmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mulmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition exp : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* base := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent_bits := exponent.["bit_length"] (| + + |) in + let* exponent_bytes := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* result := ethereum_types.numeric.U256 (| + pow (| + base, + exponent, + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signextend : 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. + + *) + let* byte_num := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..7d747a72ef --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/bitwise.v @@ -0,0 +1,245 @@ +(* +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 muir_glacier.vm.gas. +Require muir_glacier.vm.stack. + +Definition bitwise_and : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_or : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_xor : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_not : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition get_byte : 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. + + *) + let* byte_index := stack.pop (| + evm.["stack"] + |) in + let* word := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shl : 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. + *) + let* shift := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shr : 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. + *) + let* shift := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_sar : 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. + *) + let* shift := int (| + stack.pop (| + evm.["stack"] + |) + |) in + let* signed_value := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..4fc228e55d --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/block.v @@ -0,0 +1,207 @@ +(* +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 muir_glacier.vm.gas. +Require muir_glacier.vm.stack. + +Definition block_hash : 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. + + *) + let* block_number := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOCK_HASH + |) in + let* max_block_number := (* TODO expression *) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + + +Definition coinbase : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["coinbase"] + |) + |) in + (* TODO statement *) + + +Definition timestamp : 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 (| + evm.["stack"], + evm.["env"].["time"] + |) in + (* TODO statement *) + + +Definition number : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["number"] + |) + |) in + (* TODO statement *) + + +Definition difficulty : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["difficulty"] + |) + |) in + (* TODO statement *) + + +Definition gas_limit : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_limit"] + |) + |) in + (* TODO statement *) + + +Definition chain_id : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["chain_id"] + |) + |) in + (* TODO statement *) + 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..fa5d4164ce --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/comparison.v @@ -0,0 +1,206 @@ +(* +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 muir_glacier.vm.gas. +Require muir_glacier.vm.stack. + +Definition less_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_less_than : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition greater_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_greater_than : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition equal : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition is_zero : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..a8793d599e --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/control_flow.v @@ -0,0 +1,156 @@ +(* +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 muir_glacier.vm.gas. +Require muir_glacier.vm.exceptions. +Require muir_glacier.vm.stack. + +Definition stop : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition jump : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_MID + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition jumpi : 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. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* conditional_value := stack.pop (| + evm.["stack"] + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_HIGH + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition pc : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["pc"] + |) + |) in + (* TODO statement *) + + +Definition gas_left : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + + +Definition jumpdest : 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 *) + (* TODO statement *) + 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..7d0903a808 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/environment.v @@ -0,0 +1,556 @@ +(* +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 muir_glacier.fork_types. +Require muir_glacier.state. +Require muir_glacier.utils.address. +Require muir_glacier.vm.memory. +Require muir_glacier.vm.exceptions. +Require muir_glacier.vm.gas. +Require muir_glacier.vm.stack. + +Definition address : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["current_target"] + |) + |) in + (* TODO statement *) + + +Definition balance : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BALANCE + |) in + let* balance := state.get_account (| + evm.["env"].["state"], + address + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition origin : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["origin"] + |) + |) in + (* TODO statement *) + + +Definition caller : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["caller"] + |) + |) in + (* TODO statement *) + + +Definition callvalue : 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 (| + evm.["stack"], + evm.["message"].["value"] + |) in + (* TODO statement *) + + +Definition calldataload : 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. + + *) + let* start_index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + start_index, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + value + |) + |) in + (* TODO statement *) + + +Definition calldatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["message"].["data"] + |) + |) + |) in + (* TODO statement *) + + +Definition calldatacopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* data_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + data_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition codesize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["code"] + |) + |) + |) in + (* TODO statement *) + + +Definition codecopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["code"], + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition gasprice : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_price"] + |) + |) in + (* TODO statement *) + + +Definition extcodesize : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_EXTERNAL + |) in + let* codesize := ethereum_types.numeric.U256 (| + len (| + state.get_account (| + evm.["env"].["state"], + address + |).["code"] + |) + |) in + do* stack.push (| + evm.["stack"], + codesize + |) in + (* TODO statement *) + + +Definition extcodecopy : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* code := state.get_account (| + evm.["env"].["state"], + address + |).["code"] in + let* value := vm.memory.buffer_read (| + code, + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition returndatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["return_data"] + |) + |) + |) in + (* TODO statement *) + + +Definition returndatacopy : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* return_data_start_position := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition extcodehash : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_CODE_HASH + |) in + let* account := state.get_account (| + evm.["env"].["state"], + address + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + codehash + |) in + (* TODO statement *) + + +Definition self_balance : 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 + let* balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + 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..ffa8a22592 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/keccak.v @@ -0,0 +1,67 @@ +(* +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 muir_glacier.vm.gas. +Require muir_glacier.vm.memory. +Require muir_glacier.vm.stack. + +Definition keccak : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* word_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + let* hash := ethereum.crypto.hash.keccak256 (| + data + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + 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..dca012fe14 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/log.v @@ -0,0 +1,61 @@ +(* +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 muir_glacier.blocks. +Require muir_glacier.vm.exceptions. +Require muir_glacier.vm.gas. +Require muir_glacier.vm.memory. +Require muir_glacier.vm.stack. + +Definition log_n : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* topics := (* TODO expression *) in + (* TODO statement *) + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* log_entry := blocks.Log (| + + |) in + (* TODO assignment *) + (* TODO statement *) + 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..d45d56bf00 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/memory.v @@ -0,0 +1,158 @@ +(* +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 muir_glacier.vm.gas. +Require muir_glacier.vm.memory. +Require muir_glacier.vm.stack. + +Definition mstore : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* memory.memory_write (| + evm.["memory"], + start_position, + value + |) in + (* TODO statement *) + + +Definition mstore8 : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + (* TODO expression *) + |) in + do* memory.memory_write (| + evm.["memory"], + start_position, + normalized_bytes_value + |) in + (* TODO statement *) + + +Definition mload : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.memory_read_bytes (| + evm.["memory"], + start_position, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition msize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["memory"] + |) + |) + |) in + (* TODO statement *) + 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..f135418b24 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/stack.v @@ -0,0 +1,133 @@ +(* +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 muir_glacier.vm.exceptions. +Require muir_glacier.vm.gas. +Require muir_glacier.vm.memory. + +Definition pop : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* stack.["pop"] (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BASE + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition push_n : 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 + let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + evm.["code"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + num_bytes + |) + |) + |) in + do* stack.["push"] (| + evm.["stack"], + data_to_push + |) in + (* TODO statement *) + + +Definition dup_n : 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 *) + let* data_to_duplicate := (* TODO expression *) in + do* stack.["push"] (| + evm.["stack"], + data_to_duplicate + |) in + (* TODO statement *) + + +Definition swap_n : 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 *) + (* TODO statement *) + 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..1eb4772eb7 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/storage.v @@ -0,0 +1,96 @@ +(* +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 muir_glacier.state. +Require muir_glacier.vm.exceptions. +Require muir_glacier.vm.gas. +Require muir_glacier.vm.stack. + +Definition sload : 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. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_SLOAD + |) in + let* value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition sstore : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + (* TODO statement *) + let* original_value := state.get_storage_original (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + let* current_value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + do* state.set_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + 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..e7fcb0f5f5 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/system.v @@ -0,0 +1,581 @@ +(* +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 muir_glacier.fork_types. +Require muir_glacier.state. +Require muir_glacier.utils.address. +Require muir_glacier.vm.exceptions. +Require muir_glacier.vm.gas. +Require muir_glacier.vm.memory. +Require muir_glacier.vm.stack. + +Definition generic_create : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + let* create_message_gas := gas.max_message_call_gas (| + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + let* sender_address := evm.["message"].["current_target"] in + let* sender := state.get_account (| + evm.["env"].["state"], + sender_address + |) in + (* TODO statement *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) in + do* state.increment_nonce (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |) in + let* child_message := Message (| + + |) in + let* child_evm := process_create_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + + +Definition create : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_contract_address (| + evm.["message"].["current_target"], + state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["nonce"] + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size + |) in + (* TODO statement *) + + +Definition create2 : 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. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* salt := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* call_data_words := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_create2_contract_address (| + evm.["message"].["current_target"], + salt, + memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size + |) in + (* TODO statement *) + + +Definition return_ : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + + +Definition generic_call : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_input_start_position, + memory_input_size + |) in + let* code := state.get_account (| + evm.["env"].["state"], + code_address + |).["code"] in + let* child_message := Message (| + + |) in + let* child_evm := process_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + let* actual_output_size := min (| + memory_output_size, + ethereum_types.numeric.U256 (| + len (| + child_evm.["output"] + |) + |) + |) in + do* memory.memory_write (| + evm.["memory"], + memory_output_start_position, + (* TODO expression *) + |) in + + +Definition call : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* create_gas_cost := (* TODO expression *) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition callcode : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* to := evm.["message"].["current_target"] in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition selfdestruct : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* beneficiary := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* gas_cost := gas.GAS_SELF_DESTRUCT in + (* TODO statement *) + let* originator := evm.["message"].["current_target"] in + let* refunded_accounts := evm.["accounts_to_delete"] in + let* parent_evm := evm.["message"].["parent_evm"] in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + let* beneficiary_balance := state.get_account (| + evm.["env"].["state"], + beneficiary + |).["balance"] in + let* originator_balance := state.get_account (| + evm.["env"].["state"], + originator + |).["balance"] in + do* state.set_account_balance (| + evm.["env"].["state"], + beneficiary, + (* TODO expression *) + |) in + do* state.set_account_balance (| + evm.["env"].["state"], + originator, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* evm.["accounts_to_delete"].["add"] (| + originator + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition delegatecall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + gas.GAS_CALL + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + evm.["message"].["value"], + evm.["message"].["caller"], + evm.["message"].["current_target"], + code_address, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition staticcall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + gas.GAS_CALL + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + evm.["message"].["current_target"], + to, + to, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition revert : 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. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + extend_memory.["cost"] + |) in + (* TODO statement *) + let* output := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + 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..10947850c4 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/interpreter.v @@ -0,0 +1,159 @@ +(* +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 muir_glacier.blocks. +Require muir_glacier.fork_types. +Require muir_glacier.state. +Require muir_glacier.vm. +Require muir_glacier.vm.gas. +Require muir_glacier.vm.precompiled_contracts.mapping. +Require muir_glacier.vm.exceptions. +Require muir_glacier.vm.instructions. +Require muir_glacier.vm.runtime. + +Definition process_message_call : M unit := + (* + 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 *) + let* tx_end := ethereum.trace.TransactionEnd (| + (* TODO expression *), + evm.["output"], + evm.["error"] + |) in + do* ethereum.trace.evm_trace (| + evm, + tx_end + |) in + (* TODO statement *) + + +Definition process_create_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.destroy_storage (| + env.["state"], + message.["current_target"] + |) in + do* state.mark_account_created (| + env.["state"], + message.["current_target"] + |) in + do* state.increment_nonce (| + env.["state"], + message.["current_target"] + |) in + let* evm := process_message (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.touch_account (| + env.["state"], + message.["current_target"] + |) in + (* TODO statement *) + let* evm := execute_code (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition execute_code : M unit := + (* + 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 + *) + let* code := message.["code"] in + let* valid_jump_destinations := runtime.get_valid_jump_destinations (| + code + |) in + let* evm := Evm (| + + |) in + (* TODO statement *) + (* TODO statement *) + 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..94b6a44639 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/memory.v @@ -0,0 +1,75 @@ +(* +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 : 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 *) + + +Definition memory_read_bytes : M unit := + (* + 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 *) + + +Definition buffer_read : M unit := + (* + 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 *) + 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..74fc41487e --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/__init__.v @@ -0,0 +1,16 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require 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..b1f35001eb --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,187 @@ +(* +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 muir_glacier.vm. +Require muir_glacier.vm.gas. +Require muir_glacier.vm.memory. +Require muir_glacier.vm.exceptions. + +Definition alt_bn128_add : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* x1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x1_bytes + |) + |) in + let* y1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y1_bytes + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := (* TODO expression *) in + (* TODO assignment *) + + +Definition alt_bn128_mul : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* n := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := p0.["mul_by"] (| + n + |) in + (* TODO assignment *) + + +Definition alt_bn128_pairing_check : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..f2119749e6 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,41 @@ +(* +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 muir_glacier.vm. +Require muir_glacier.vm.gas. +Require muir_glacier.vm.exceptions. + +Definition blake2f : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + (* TODO statement *) + let* blake2b := ethereum.crypto.blake2.Blake2b (| + + |) in + (* TODO assignment *) + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + 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..0b8c561a04 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,93 @@ +(* +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 muir_glacier.vm. +Require muir_glacier.vm.gas. +Require muir_glacier.vm.memory. + +Definition ecrecover : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_ECRECOVER + |) in + let* message_hash_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* message_hash := ethereum.crypto.hash.Hash32 (| + message_hash_bytes + |) in + let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + address, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..323b6dfe57 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/identity.v @@ -0,0 +1,36 @@ +(* +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 muir_glacier.vm. +Require muir_glacier.vm.gas. + +Definition identity : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..3d48e2e1dd --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/mapping.v @@ -0,0 +1,23 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require muir_glacier.fork_types. +Require muir_glacier.vm.precompiled_contracts.alt_bn128. +Require muir_glacier.vm.precompiled_contracts.blake2f. +Require muir_glacier.vm.precompiled_contracts.ecrecover. +Require muir_glacier.vm.precompiled_contracts.identity. +Require muir_glacier.vm.precompiled_contracts.modexp. +Require muir_glacier.vm.precompiled_contracts.ripemd160. +Require 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..588717745d --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/modexp.v @@ -0,0 +1,202 @@ +(* +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 muir_glacier.vm. +Require muir_glacier.vm.gas. +Require muir_glacier.vm.memory. + +Definition modexp : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + let* data := evm.["message"].["data"] in + let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_start := (* TODO expression *) in + let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + min (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + exp_length + |) + |) + |) in + do* vm.gas.charge_gas (| + evm, + gas_cost (| + base_length, + modulus_length, + exp_length, + exp_head + |) + |) in + (* TODO statement *) + let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + base_length + |) + |) in + let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + exp_length + |) + |) in + let* modulus_start := (* TODO expression *) in + let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + modulus_start, + modulus_length + |) + |) in + (* TODO statement *) + + +Definition complexity : M unit := + (* + 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. + *) + let* max_length := max (| + ethereum_types.numeric.Uint (| + base_length + |), + ethereum_types.numeric.Uint (| + modulus_length + |) + |) in + (* TODO statement *) + + +Definition iterations : M unit := + (* + 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 *) + + +Definition gas_cost : M unit := + (* + 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. + *) + let* multiplication_complexity := complexity (| + base_length, + modulus_length + |) in + let* iteration_count := iterations (| + exponent_length, + exponent_head + |) in + let* cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..bc5e73dd3c --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,42 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + let* hash_bytes := hashlib.["new"] (| + (* TODO expression *), + data + |).["digest"] (| + + |) in + let* padded_hash := left_pad_zero_bytes (| + hash_bytes, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..da6972d411 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/sha256.v @@ -0,0 +1,32 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..61466cb23b --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/runtime.v @@ -0,0 +1,49 @@ +(* +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 muir_glacier.vm.instructions. + +Definition get_valid_jump_destinations : M unit := + (* + 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. + *) + let* valid_jump_destinations := set (| + + |) in + let* pc := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..a6a417a566 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/stack.v @@ -0,0 +1,53 @@ +(* +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 muir_glacier.vm.exceptions. + +Definition pop : M unit := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + + +Definition push : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + 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..e5f250b1c0 --- /dev/null +++ b/coq/ethereum/paris/__init__.v @@ -0,0 +1,10 @@ +(* +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/translation/blocks.v b/coq/ethereum/paris/blocks.v similarity index 87% rename from coq/translation/blocks.v rename to coq/ethereum/paris/blocks.v index 5ebd4d4748..fc5a46467f 100644 --- a/coq/translation/blocks.v +++ b/coq/ethereum/paris/blocks.v @@ -14,6 +14,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require crypto.hash. -Require fork_types. -Require transactions. +Require ..crypto.hash. +Require paris.fork_types. +Require 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..9a216ffea9 --- /dev/null +++ b/coq/ethereum/paris/bloom.v @@ -0,0 +1,66 @@ +(* +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 paris.blocks. +Require paris.fork_types. + +Definition add_to_bloom : 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. + *) + let* hash := ethereum.crypto.hash.keccak256 (| + bloom_entry + |) in + (* TODO statement *) + + +Definition logs_bloom : M unit := + (* + 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 *) + 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..137ea143f6 --- /dev/null +++ b/coq/ethereum/paris/exceptions.v @@ -0,0 +1,6 @@ +(* +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..31675ef605 --- /dev/null +++ b/coq/ethereum/paris/fork.v @@ -0,0 +1,647 @@ +(* +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 paris.blocks. +Require paris.bloom. +Require paris.fork_types. +Require paris.state. +Require paris.transactions. +Require paris.trie. +Require paris.utils.message. +Require paris.vm.interpreter. + +Definition apply_fork : M unit := + (* + 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 *) + + +Definition get_last_256_block_hashes : M unit := + (* + 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. + *) + let* recent_blocks := (* TODO expression *) in + (* TODO statement *) + let* recent_block_hashes := (* TODO expression *) in + (* TODO statement *) + let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *).["header"] + |) + |) in + do* recent_block_hashes.["append"] (| + most_recent_block_hash + |) in + (* TODO statement *) + + +Definition state_transition : 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`. + *) + let* parent_header := (* TODO expression *).["header"] in + do* validate_header (| + block.["header"], + parent_header + |) in + (* TODO statement *) + let* apply_body_output := apply_body (| + chain.["state"], + get_last_256_block_hashes (| + chain + |), + block.["header"].["coinbase"], + block.["header"].["number"], + block.["header"].["base_fee_per_gas"], + block.["header"].["gas_limit"], + block.["header"].["timestamp"], + block.["header"].["prev_randao"], + block.["transactions"], + chain.["chain_id"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* chain.["blocks"].["append"] (| + block + |) in + (* TODO statement *) + + +Definition calculate_base_fee_per_gas : M unit := + (* + 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. + *) + let* parent_gas_target := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_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 *) + let* expected_base_fee_per_gas := calculate_base_fee_per_gas (| + header.["gas_limit"], + parent_header.["gas_limit"], + parent_header.["gas_used"], + parent_header.["base_fee_per_gas"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* block_parent_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + parent_header + |) + |) in + (* TODO statement *) + + +Definition check_transaction : M unit := + (* + 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 *) + let* sender_address := recover_sender (| + chain_id, + tx + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition make_receipt : M unit := + (* + 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. + *) + let* receipt := blocks.Receipt (| + + |) in + (* TODO statement *) + + +Definition apply_body : M unit := + (* + 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. + *) + let* gas_available := block_gas_limit in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* block_gas_used := (* TODO expression *) in + let* block_logs_bloom := bloom.logs_bloom (| + block_logs + |) in + (* TODO statement *) + + +Definition process_transaction : M unit := + (* + 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 *) + let* sender := env.["origin"] in + let* sender_account := state.get_account (| + env.["state"], + sender + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* effective_gas_fee := (* TODO expression *) in + let* gas := (* TODO expression *) in + do* state.increment_nonce (| + env.["state"], + sender + |) in + let* sender_balance_after_gas_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + ethereum_types.numeric.U256 (| + sender_balance_after_gas_fee + |) + |) in + let* preaccessed_addresses := set (| + + |) in + let* preaccessed_storage_keys := set (| + + |) in + (* TODO statement *) + let* message := utils.message.prepare_message (| + sender, + tx.["to"], + tx.["value"], + tx.["data"], + gas, + env + |) in + let* output := vm.interpreter.process_message_call (| + message, + env + |) in + let* gas_used := (* TODO expression *) in + let* gas_refund := min (| + (* TODO expression *), + ethereum_types.numeric.Uint (| + output.["refund_counter"] + |) + |) in + let* gas_refund_amount := (* TODO expression *) in + let* priority_fee_per_gas := (* TODO expression *) in + let* transaction_fee := (* TODO expression *) in + let* total_gas_used := (* TODO expression *) in + let* sender_balance_after_refund := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + sender_balance_after_refund + |) in + let* coinbase_balance_after_mining_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_transaction : M unit := + (* + 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 *) + + +Definition calculate_intrinsic_cost : M unit := + (* + 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. + *) + let* data_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + let* access_list_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + + +Definition recover_sender : M unit := + (* + 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 *) + + +Definition signing_hash_pre155 : M unit := + (* + 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 *) + + +Definition signing_hash_155 : M unit := + (* + 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 *) + + +Definition signing_hash_2930 : M unit := + (* + 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 *) + + +Definition signing_hash_1559 : M unit := + (* + 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 *) + + +Definition compute_header_hash : M unit := + (* + 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 *) + + +Definition check_gas_limit : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + 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..14de99d5e5 --- /dev/null +++ b/coq/ethereum/paris/fork_types.v @@ -0,0 +1,29 @@ +(* +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 ..crypto.hash. + +Definition encode_account : M unit := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + 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..0f51028736 --- /dev/null +++ b/coq/ethereum/paris/state.v @@ -0,0 +1,572 @@ +(* +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 paris.fork_types. +Require paris.trie. + +Definition close_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 *) + + +Definition begin_transaction : 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* state.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + + +Definition commit_transaction : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* state.["_snapshots"].["pop"] (| + + |) in + (* TODO statement *) + + +Definition rollback_transaction : 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 *) + + +Definition get_account : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition get_account_optional : M unit := + (* + 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. + *) + let* account := trie.trie_get (| + state.["_main_trie"], + address + |) in + (* TODO statement *) + + +Definition set_account : 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 (| + state.["_main_trie"], + address, + account + |) in + + +Definition destroy_account : 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* destroy_storage (| + state, + address + |) in + do* set_account (| + state, + address, + (* TODO expression *) + |) in + + +Definition destroy_storage : 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 *) + + +Definition mark_account_created : 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* state.["created_accounts"].["add"] (| + address + |) in + + +Definition get_storage : M unit := + (* + 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. + *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_storage : 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 *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition storage_root : M unit := + (* + 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 *) + + +Definition state_root : M unit := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition account_exists : M unit := + (* + 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 *) + + +Definition account_has_code_or_nonce : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_empty : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition account_exists_and_is_empty : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_alive : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition modify_state : M unit := + (* + Modify an `Account` in the `State`. + *) + do* set_account (| + state, + address, + ethereum_types.frozen.modify (| + get_account (| + state, + address + |), + f + |) + |) in + + +Definition move_ether : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* modify_state (| + state, + sender_address, + reduce_sender_balance + |) in + do* modify_state (| + state, + recipient_address, + increase_recipient_balance + |) in + + +Definition set_account_balance : 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* modify_state (| + state, + address, + set_balance + |) in + + +Definition touch_account : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + + +Definition increment_nonce : 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* modify_state (| + state, + address, + increase_nonce + |) in + + +Definition set_code : 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* modify_state (| + state, + address, + write_code + |) in + + +Definition get_storage_original : M unit := + (* + 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 *) + let* original_account_trie := original_trie.["get"] (| + address + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + 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..28f2796b42 --- /dev/null +++ b/coq/ethereum/paris/transactions.v @@ -0,0 +1,27 @@ +(* +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 paris.exceptions. +Require paris.fork_types. + +Definition encode_transaction : M unit := + (* + Encode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + + +Definition decode_transaction : M unit := + (* + Decode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + 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..548de91e1c --- /dev/null +++ b/coq/ethereum/paris/trie.v @@ -0,0 +1,274 @@ +(* +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 : M unit := + (* + 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 *) + let* encoded := rlp.["encode"] (| + unencoded + |) in + (* TODO statement *) + + +Definition encode_node : M unit := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + + +Definition copy_trie : M unit := + (* + 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 *) + + +Definition trie_set : 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 *) + + +Definition trie_get : M unit := + (* + 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 *) + + +Definition common_prefix_length : M unit := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition nibble_list_to_compact : M unit := + (* + 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. + *) + let* compact := bytearray (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_nibble_list : M unit := + (* + 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. + *) + let* nibble_list := bytearray (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _prepare_trie : M unit := + (* + 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 *) + + +Definition root : M unit := + (* + 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. + *) + let* obj := _prepare_trie (| + trie, + get_storage_root + |) in + let* root_node := encode_internal_node (| + patricialize (| + obj, + Uint (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + + +Definition patricialize : M unit := + (* + 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 *) + let* arbitrary_key := next (| + iter (| + obj + |) + |) in + (* TODO statement *) + let* substring := (* TODO expression *) in + let* prefix_length := len (| + substring + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..beff4482b1 --- /dev/null +++ b/coq/ethereum/paris/utils/__init__.v @@ -0,0 +1,4 @@ +(* +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..eee092b436 --- /dev/null +++ b/coq/ethereum/paris/utils/address.v @@ -0,0 +1,99 @@ +(* +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 paris.fork_types. + +Definition to_address : M unit := + (* + 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 *) + + +Definition compute_contract_address : M unit := + (* + 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. + *) + let* computed_address := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *) + |) + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition compute_create2_contract_address : M unit := + (* + 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. + *) + let* preimage := (* TODO expression *) in + let* computed_address := ethereum.crypto.hash.keccak256 (| + preimage + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + 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..6903617d0b --- /dev/null +++ b/coq/ethereum/paris/utils/hexadecimal.v @@ -0,0 +1,68 @@ +(* +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 paris.fork_types. + +Definition hex_to_root : M unit := + (* + 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 *) + + +Definition hex_to_bloom : M unit := + (* + 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 *) + + +Definition hex_to_address : M unit := + (* + 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 *) + 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..3b5a529a5b --- /dev/null +++ b/coq/ethereum/paris/utils/message.v @@ -0,0 +1,82 @@ +(* +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 paris.fork_types. +Require paris.state. +Require paris.vm. +Require paris.vm.precompiled_contracts.mapping. +Require paris.utils.address. + +Definition prepare_message : M unit := + (* + 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 *) + let* accessed_addresses := set (| + + |) in + do* accessed_addresses.["add"] (| + current_target + |) in + do* accessed_addresses.["add"] (| + caller + |) in + do* accessed_addresses.["update"] (| + vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS.["keys"] (| + + |) + |) in + do* accessed_addresses.["update"] (| + preaccessed_addresses + |) in + (* TODO statement *) + 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..ee1ef60da7 --- /dev/null +++ b/coq/ethereum/paris/vm/__init__.v @@ -0,0 +1,69 @@ +(* +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 paris.blocks. +Require paris.fork_types. +Require paris.state. +Require paris.vm.precompiled_contracts. + +Definition incorporate_child_on_success : 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* evm.["accounts_to_delete"].["update"] (| + child_evm.["accounts_to_delete"] + |) in + do* evm.["touched_accounts"].["update"] (| + child_evm.["touched_accounts"] + |) in + (* TODO statement *) + do* evm.["accessed_addresses"].["update"] (| + child_evm.["accessed_addresses"] + |) in + do* evm.["accessed_storage_keys"].["update"] (| + child_evm.["accessed_storage_keys"] + |) in + + +Definition incorporate_child_on_error : 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 *) + (* TODO statement *) + 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..1784494410 --- /dev/null +++ b/coq/ethereum/paris/vm/exceptions.v @@ -0,0 +1,15 @@ +(* +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..526d353822 --- /dev/null +++ b/coq/ethereum/paris/vm/gas.v @@ -0,0 +1,151 @@ +(* +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 paris.vm.exceptions. + +Definition charge_gas : 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 (| + int (| + amount + |) + |) + |) in + (* TODO statement *) + + +Definition calculate_memory_gas_cost : M unit := + (* + 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. + *) + let* size_in_words := (* TODO expression *) in + let* linear_cost := (* TODO expression *) in + let* quadratic_cost := (* TODO expression *) in + let* total_gas_cost := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_gas_extend_memory : M unit := + (* + 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` + *) + let* size_to_extend := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* to_be_paid := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* current_size := ethereum_types.numeric.Uint (| + len (| + memory + |) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_message_call_gas : M unit := + (* + 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` + *) + let* call_stipend := (* TODO expression *) in + (* TODO statement *) + let* gas := min (| + gas, + max_message_call_gas (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + + +Definition max_message_call_gas : M unit := + (* + 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 *) + 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..b36b1ebfef --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/__init__.v @@ -0,0 +1,15 @@ +(* +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..73f9cdd9d2 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/arithmetic.v @@ -0,0 +1,387 @@ +(* +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 paris.vm.gas. +Require paris.vm.stack. + +Definition add : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_add"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition sub : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_sub"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mul : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + let* result := x.["wrapping_mul"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition div : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |) in + let* divisor := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + quotient + |) in + (* TODO statement *) + + +Definition sdiv : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* divisor := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + quotient + |) + |) in + (* TODO statement *) + + +Definition mod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + remainder + |) in + (* TODO statement *) + + +Definition smod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* y := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + remainder + |) + |) in + (* TODO statement *) + + +Definition addmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mulmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition exp : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* base := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent_bits := exponent.["bit_length"] (| + + |) in + let* exponent_bytes := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* result := ethereum_types.numeric.U256 (| + pow (| + base, + exponent, + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signextend : 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. + + *) + let* byte_num := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..b1cacf6745 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/bitwise.v @@ -0,0 +1,245 @@ +(* +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 paris.vm.gas. +Require paris.vm.stack. + +Definition bitwise_and : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_or : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_xor : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_not : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition get_byte : 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. + + *) + let* byte_index := stack.pop (| + evm.["stack"] + |) in + let* word := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shl : 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. + *) + let* shift := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shr : 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. + *) + let* shift := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_sar : 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. + *) + let* shift := int (| + stack.pop (| + evm.["stack"] + |) + |) in + let* signed_value := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..8904838929 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/block.v @@ -0,0 +1,249 @@ +(* +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 paris.vm.gas. +Require paris.vm.stack. + +Definition block_hash : 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`. + *) + let* block_number := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOCK_HASH + |) in + let* max_block_number := (* TODO expression *) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + + +Definition coinbase : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["coinbase"] + |) + |) in + (* TODO statement *) + + +Definition timestamp : 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 (| + evm.["stack"], + evm.["env"].["time"] + |) in + (* TODO statement *) + + +Definition number : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["number"] + |) + |) in + (* TODO statement *) + + +Definition prev_randao : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["prev_randao"] + |) + |) in + (* TODO statement *) + + +Definition gas_limit : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_limit"] + |) + |) in + (* TODO statement *) + + +Definition chain_id : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["chain_id"] + |) + |) in + (* TODO statement *) + 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..de04583d9c --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/comparison.v @@ -0,0 +1,206 @@ +(* +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 paris.vm.gas. +Require paris.vm.stack. + +Definition less_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_less_than : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition greater_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_greater_than : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition equal : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition is_zero : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..5bb7f0c9e8 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/control_flow.v @@ -0,0 +1,156 @@ +(* +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 paris.vm.gas. +Require paris.vm.exceptions. +Require paris.vm.stack. + +Definition stop : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition jump : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_MID + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition jumpi : 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. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* conditional_value := stack.pop (| + evm.["stack"] + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_HIGH + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition pc : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["pc"] + |) + |) in + (* TODO statement *) + + +Definition gas_left : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + + +Definition jumpdest : 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 *) + (* TODO statement *) + 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..09fedbff2f --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/environment.v @@ -0,0 +1,568 @@ +(* +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 paris.fork_types. +Require paris.state. +Require paris.utils.address. +Require paris.vm.memory. +Require paris.vm.exceptions. +Require paris.vm.gas. +Require paris.vm.stack. + +Definition address : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["current_target"] + |) + |) in + (* TODO statement *) + + +Definition balance : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* balance := state.get_account (| + evm.["env"].["state"], + address + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition origin : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["origin"] + |) + |) in + (* TODO statement *) + + +Definition caller : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["caller"] + |) + |) in + (* TODO statement *) + + +Definition callvalue : 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 (| + evm.["stack"], + evm.["message"].["value"] + |) in + (* TODO statement *) + + +Definition calldataload : 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. + + *) + let* start_index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + start_index, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + value + |) + |) in + (* TODO statement *) + + +Definition calldatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["message"].["data"] + |) + |) + |) in + (* TODO statement *) + + +Definition calldatacopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* data_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + data_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition codesize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["code"] + |) + |) + |) in + (* TODO statement *) + + +Definition codecopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["code"], + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition gasprice : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_price"] + |) + |) in + (* TODO statement *) + + +Definition extcodesize : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* codesize := ethereum_types.numeric.U256 (| + len (| + state.get_account (| + evm.["env"].["state"], + address + |).["code"] + |) + |) in + do* stack.push (| + evm.["stack"], + codesize + |) in + (* TODO statement *) + + +Definition extcodecopy : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* code := state.get_account (| + evm.["env"].["state"], + address + |).["code"] in + let* value := vm.memory.buffer_read (| + code, + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition returndatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["return_data"] + |) + |) + |) in + (* TODO statement *) + + +Definition returndatacopy : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* return_data_start_position := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition extcodehash : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* account := state.get_account (| + evm.["env"].["state"], + address + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + codehash + |) in + (* TODO statement *) + + +Definition self_balance : 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 + let* balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition base_fee : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["base_fee_per_gas"] + |) + |) in + (* TODO statement *) + 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..a638f16e31 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/keccak.v @@ -0,0 +1,67 @@ +(* +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 paris.vm.gas. +Require paris.vm.memory. +Require paris.vm.stack. + +Definition keccak : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* word_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + let* hash := ethereum.crypto.hash.keccak256 (| + data + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + 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..60917ddfff --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/log.v @@ -0,0 +1,61 @@ +(* +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 paris.blocks. +Require paris.vm.exceptions. +Require paris.vm.gas. +Require paris.vm.memory. +Require paris.vm.stack. + +Definition log_n : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* topics := (* TODO expression *) in + (* TODO statement *) + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* log_entry := blocks.Log (| + + |) in + (* TODO assignment *) + (* TODO statement *) + 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..a1a0dda6df --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/memory.v @@ -0,0 +1,158 @@ +(* +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 paris.vm.gas. +Require paris.vm.memory. +Require paris.vm.stack. + +Definition mstore : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* memory.memory_write (| + evm.["memory"], + start_position, + value + |) in + (* TODO statement *) + + +Definition mstore8 : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + (* TODO expression *) + |) in + do* memory.memory_write (| + evm.["memory"], + start_position, + normalized_bytes_value + |) in + (* TODO statement *) + + +Definition mload : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.memory_read_bytes (| + evm.["memory"], + start_position, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition msize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["memory"] + |) + |) + |) in + (* TODO statement *) + 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..091b7d3fb3 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/stack.v @@ -0,0 +1,133 @@ +(* +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 paris.vm.exceptions. +Require paris.vm.gas. +Require paris.vm.memory. + +Definition pop : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* stack.["pop"] (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BASE + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition push_n : 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 + let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + evm.["code"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + num_bytes + |) + |) + |) in + do* stack.["push"] (| + evm.["stack"], + data_to_push + |) in + (* TODO statement *) + + +Definition dup_n : 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 *) + let* data_to_duplicate := (* TODO expression *) in + do* stack.["push"] (| + evm.["stack"], + data_to_duplicate + |) in + (* TODO statement *) + + +Definition swap_n : 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 *) + (* TODO statement *) + 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..4df30cb924 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/storage.v @@ -0,0 +1,97 @@ +(* +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 paris.state. +Require paris.vm.exceptions. +Require paris.vm.gas. +Require paris.vm.stack. + +Definition sload : 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. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + (* TODO statement *) + let* value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition sstore : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + (* TODO statement *) + let* original_value := state.get_storage_original (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + let* current_value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + let* gas_cost := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + do* state.set_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + 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..d5867e896f --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/system.v @@ -0,0 +1,585 @@ +(* +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 paris.fork_types. +Require paris.state. +Require paris.utils.address. +Require paris.vm.exceptions. +Require paris.vm.gas. +Require paris.vm.memory. +Require paris.vm.stack. + +Definition generic_create : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + do* evm.["accessed_addresses"].["add"] (| + contract_address + |) in + let* create_message_gas := gas.max_message_call_gas (| + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + let* sender_address := evm.["message"].["current_target"] in + let* sender := state.get_account (| + evm.["env"].["state"], + sender_address + |) in + (* TODO statement *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) in + do* state.increment_nonce (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |) in + let* child_message := Message (| + + |) in + let* child_evm := process_create_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + + +Definition create : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_contract_address (| + evm.["message"].["current_target"], + state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["nonce"] + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size + |) in + (* TODO statement *) + + +Definition create2 : 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. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* salt := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* call_data_words := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_create2_contract_address (| + evm.["message"].["current_target"], + salt, + memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size + |) in + (* TODO statement *) + + +Definition return_ : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + + +Definition generic_call : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_input_start_position, + memory_input_size + |) in + let* code := state.get_account (| + evm.["env"].["state"], + code_address + |).["code"] in + let* child_message := Message (| + + |) in + let* child_evm := process_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + let* actual_output_size := min (| + memory_output_size, + ethereum_types.numeric.U256 (| + len (| + child_evm.["output"] + |) + |) + |) in + do* memory.memory_write (| + evm.["memory"], + memory_output_start_position, + (* TODO expression *) + |) in + + +Definition call : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* create_gas_cost := (* TODO expression *) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition callcode : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* to := evm.["message"].["current_target"] in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition selfdestruct : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* beneficiary := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* gas_cost := gas.GAS_SELF_DESTRUCT in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + let* originator := evm.["message"].["current_target"] in + let* beneficiary_balance := state.get_account (| + evm.["env"].["state"], + beneficiary + |).["balance"] in + let* originator_balance := state.get_account (| + evm.["env"].["state"], + originator + |).["balance"] in + do* state.set_account_balance (| + evm.["env"].["state"], + beneficiary, + (* TODO expression *) + |) in + do* state.set_account_balance (| + evm.["env"].["state"], + originator, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* evm.["accounts_to_delete"].["add"] (| + originator + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition delegatecall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + access_gas_cost + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + evm.["message"].["value"], + evm.["message"].["caller"], + evm.["message"].["current_target"], + code_address, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition staticcall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + access_gas_cost + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + evm.["message"].["current_target"], + to, + to, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition revert : 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. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + extend_memory.["cost"] + |) in + (* TODO statement *) + let* output := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + 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..861ecc75a7 --- /dev/null +++ b/coq/ethereum/paris/vm/interpreter.v @@ -0,0 +1,159 @@ +(* +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 paris.blocks. +Require paris.fork_types. +Require paris.state. +Require paris.vm. +Require paris.vm.gas. +Require paris.vm.precompiled_contracts.mapping. +Require paris.vm.exceptions. +Require paris.vm.instructions. +Require paris.vm.runtime. + +Definition process_message_call : M unit := + (* + 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 *) + let* tx_end := ethereum.trace.TransactionEnd (| + (* TODO expression *), + evm.["output"], + evm.["error"] + |) in + do* ethereum.trace.evm_trace (| + evm, + tx_end + |) in + (* TODO statement *) + + +Definition process_create_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.destroy_storage (| + env.["state"], + message.["current_target"] + |) in + do* state.mark_account_created (| + env.["state"], + message.["current_target"] + |) in + do* state.increment_nonce (| + env.["state"], + message.["current_target"] + |) in + let* evm := process_message (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.touch_account (| + env.["state"], + message.["current_target"] + |) in + (* TODO statement *) + let* evm := execute_code (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition execute_code : M unit := + (* + 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 + *) + let* code := message.["code"] in + let* valid_jump_destinations := runtime.get_valid_jump_destinations (| + code + |) in + let* evm := Evm (| + + |) in + (* TODO statement *) + (* TODO statement *) + 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..94b6a44639 --- /dev/null +++ b/coq/ethereum/paris/vm/memory.v @@ -0,0 +1,75 @@ +(* +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 : 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 *) + + +Definition memory_read_bytes : M unit := + (* + 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 *) + + +Definition buffer_read : M unit := + (* + 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 *) + 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/translation/vm/precompiled_contracts/__init__.v b/coq/ethereum/paris/vm/precompiled_contracts/__init__.v similarity index 87% rename from coq/translation/vm/precompiled_contracts/__init__.v rename to coq/ethereum/paris/vm/precompiled_contracts/__init__.v index 767782fbe3..80a08b3bf2 100644 --- a/coq/translation/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/paris/vm/precompiled_contracts/__init__.v @@ -13,4 +13,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require utils.hexadecimal. +Require 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..3273b06ff2 --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,187 @@ +(* +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 paris.vm. +Require paris.vm.gas. +Require paris.vm.memory. +Require paris.vm.exceptions. + +Definition alt_bn128_add : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* x1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x1_bytes + |) + |) in + let* y1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y1_bytes + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := (* TODO expression *) in + (* TODO assignment *) + + +Definition alt_bn128_mul : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* n := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := p0.["mul_by"] (| + n + |) in + (* TODO assignment *) + + +Definition alt_bn128_pairing_check : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..3655e229ef --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,41 @@ +(* +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 paris.vm. +Require paris.vm.gas. +Require paris.vm.exceptions. + +Definition blake2f : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + (* TODO statement *) + let* blake2b := ethereum.crypto.blake2.Blake2b (| + + |) in + (* TODO assignment *) + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + 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..e91c7a9c9f --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,93 @@ +(* +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 paris.vm. +Require paris.vm.gas. +Require paris.vm.memory. + +Definition ecrecover : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_ECRECOVER + |) in + let* message_hash_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* message_hash := ethereum.crypto.hash.Hash32 (| + message_hash_bytes + |) in + let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + address, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..c12960e71a --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/identity.v @@ -0,0 +1,36 @@ +(* +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 paris.vm. +Require paris.vm.gas. + +Definition identity : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..f746acb2a9 --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/mapping.v @@ -0,0 +1,23 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require paris.fork_types. +Require paris.vm.precompiled_contracts.alt_bn128. +Require paris.vm.precompiled_contracts.blake2f. +Require paris.vm.precompiled_contracts.ecrecover. +Require paris.vm.precompiled_contracts.identity. +Require paris.vm.precompiled_contracts.modexp. +Require paris.vm.precompiled_contracts.ripemd160. +Require 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..b723c4a781 --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/modexp.v @@ -0,0 +1,203 @@ +(* +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 paris.vm. +Require paris.vm.gas. +Require paris.vm.memory. + +Definition modexp : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + let* data := evm.["message"].["data"] in + let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_start := (* TODO expression *) in + let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + min (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + exp_length + |) + |) + |) in + do* vm.gas.charge_gas (| + evm, + gas_cost (| + base_length, + modulus_length, + exp_length, + exp_head + |) + |) in + (* TODO statement *) + let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + base_length + |) + |) in + let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + exp_length + |) + |) in + let* modulus_start := (* TODO expression *) in + let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + modulus_start, + modulus_length + |) + |) in + (* TODO statement *) + + +Definition complexity : M unit := + (* + 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. + *) + let* max_length := max (| + ethereum_types.numeric.Uint (| + base_length + |), + ethereum_types.numeric.Uint (| + modulus_length + |) + |) in + let* words := (* TODO expression *) in + (* TODO statement *) + + +Definition iterations : M unit := + (* + 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 *) + + +Definition gas_cost : M unit := + (* + 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. + *) + let* multiplication_complexity := complexity (| + base_length, + modulus_length + |) in + let* iteration_count := iterations (| + exponent_length, + exponent_head + |) in + let* cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..bc5e73dd3c --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,42 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + let* hash_bytes := hashlib.["new"] (| + (* TODO expression *), + data + |).["digest"] (| + + |) in + let* padded_hash := left_pad_zero_bytes (| + hash_bytes, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..da6972d411 --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/sha256.v @@ -0,0 +1,32 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..cb9d90bb93 --- /dev/null +++ b/coq/ethereum/paris/vm/runtime.v @@ -0,0 +1,49 @@ +(* +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 paris.vm.instructions. + +Definition get_valid_jump_destinations : M unit := + (* + 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. + *) + let* valid_jump_destinations := set (| + + |) in + let* pc := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..00cb979a94 --- /dev/null +++ b/coq/ethereum/paris/vm/stack.v @@ -0,0 +1,53 @@ +(* +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 paris.vm.exceptions. + +Definition pop : M unit := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + + +Definition push : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + 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..87c4e5c53a --- /dev/null +++ b/coq/ethereum/rlp.v @@ -0,0 +1,322 @@ +(* +.. _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 : M unit := + (* + 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 *) + + +Definition encode_bytes : M unit := + (* + 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`. + *) + let* len_raw_data := len (| + raw_bytes + |) in + (* TODO statement *) + + +Definition encode_sequence : M unit := + (* + 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`. + *) + let* joined_encodings := get_joined_encodings (| + raw_sequence + |) in + let* len_joined_encodings := len (| + joined_encodings + |) in + (* TODO statement *) + + +Definition get_joined_encodings : M unit := + (* + 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 *) + + +Definition decode : M unit := + (* + 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 *) + + +Definition decode_to : M unit := + (* + 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`. + *) + let* decoded := decode (| + encoded_data + |) in + (* TODO statement *) + + +Definition _deserialize_to : M unit := + (* TODO statement *) + + +Definition _deserialize_to : M unit := + (* TODO statement *) + + +Definition _deserialize_to : M unit := + (* TODO statement *) + + +Definition _deserialize_to_dataclass : M unit := + (* TODO statement *) + let* hints := typing.get_type_hints (| + cls + |) in + let* target_fields := dataclasses.fields (| + cls + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* result := cls (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _deserialize_to_bool : M unit := + (* TODO statement *) + + +Definition _deserialize_to_bytes : M unit := + (* TODO statement *) + (* TODO statement *) + + +Definition _deserialize_to_uint : M unit := + (* TODO statement *) + (* TODO statement *) + + +Definition _deserialize_to_annotation : M unit := + let* origin := typing.get_origin (| + annotation + |) in + (* TODO statement *) + + +Definition _deserialize_to_union : M unit := + let* arguments := typing.get_args (| + annotation + |) in + let* successes := (* TODO expression *) in + let* failures := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + + +Definition _deserialize_to_tuple : M unit := + (* TODO statement *) + let* arguments := list (| + typing.get_args (| + annotation + |) + |) in + (* TODO statement *) + let* decoded := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + + +Definition decode_to_bytes : M unit := + (* + 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 *) + + +Definition decode_to_sequence : M unit := + (* + 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 *) + + +Definition decode_joined_encodings : M unit := + (* + 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`. + *) + let* decoded_sequence := (* TODO expression *) in + let* item_start_idx := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + + +Definition decode_item_length : M unit := + (* + 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 *) + let* first_rlp_byte := (* TODO expression *) in + let* length_length := (* TODO expression *) in + let* decoded_data_length := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + + +Definition rlp_hash : M unit := + (* + 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 *) + 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..b0649052e4 --- /dev/null +++ b/coq/ethereum/shanghai/__init__.v @@ -0,0 +1,7 @@ +(* +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..74a6dc0d3b --- /dev/null +++ b/coq/ethereum/shanghai/blocks.v @@ -0,0 +1,19 @@ +(* +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 ..crypto.hash. +Require shanghai.fork_types. +Require 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..7652507dcd --- /dev/null +++ b/coq/ethereum/shanghai/bloom.v @@ -0,0 +1,66 @@ +(* +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 shanghai.blocks. +Require shanghai.fork_types. + +Definition add_to_bloom : 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. + *) + let* hash := ethereum.crypto.hash.keccak256 (| + bloom_entry + |) in + (* TODO statement *) + + +Definition logs_bloom : M unit := + (* + 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 *) + 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..137ea143f6 --- /dev/null +++ b/coq/ethereum/shanghai/exceptions.v @@ -0,0 +1,6 @@ +(* +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..f4f3907a1a --- /dev/null +++ b/coq/ethereum/shanghai/fork.v @@ -0,0 +1,658 @@ +(* +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 shanghai.blocks. +Require shanghai.bloom. +Require shanghai.fork_types. +Require shanghai.state. +Require shanghai.transactions. +Require shanghai.trie. +Require shanghai.utils.message. +Require shanghai.vm.gas. +Require shanghai.vm.interpreter. + +Definition apply_fork : M unit := + (* + 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 *) + + +Definition get_last_256_block_hashes : M unit := + (* + 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. + *) + let* recent_blocks := (* TODO expression *) in + (* TODO statement *) + let* recent_block_hashes := (* TODO expression *) in + (* TODO statement *) + let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *).["header"] + |) + |) in + do* recent_block_hashes.["append"] (| + most_recent_block_hash + |) in + (* TODO statement *) + + +Definition state_transition : 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`. + *) + let* parent_header := (* TODO expression *).["header"] in + do* validate_header (| + block.["header"], + parent_header + |) in + (* TODO statement *) + let* apply_body_output := apply_body (| + chain.["state"], + get_last_256_block_hashes (| + chain + |), + block.["header"].["coinbase"], + block.["header"].["number"], + block.["header"].["base_fee_per_gas"], + block.["header"].["gas_limit"], + block.["header"].["timestamp"], + block.["header"].["prev_randao"], + block.["transactions"], + chain.["chain_id"], + block.["withdrawals"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* chain.["blocks"].["append"] (| + block + |) in + (* TODO statement *) + + +Definition calculate_base_fee_per_gas : M unit := + (* + 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. + *) + let* parent_gas_target := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_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 *) + let* expected_base_fee_per_gas := calculate_base_fee_per_gas (| + header.["gas_limit"], + parent_header.["gas_limit"], + parent_header.["gas_used"], + parent_header.["base_fee_per_gas"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* block_parent_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + parent_header + |) + |) in + (* TODO statement *) + + +Definition check_transaction : M unit := + (* + 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 *) + let* sender_address := recover_sender (| + chain_id, + tx + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition make_receipt : M unit := + (* + 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. + *) + let* receipt := blocks.Receipt (| + + |) in + (* TODO statement *) + + +Definition apply_body : M unit := + (* + 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. + *) + let* gas_available := block_gas_limit in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* block_gas_used := (* TODO expression *) in + let* block_logs_bloom := bloom.logs_bloom (| + block_logs + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_transaction : M unit := + (* + 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 *) + let* sender := env.["origin"] in + let* sender_account := state.get_account (| + env.["state"], + sender + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* effective_gas_fee := (* TODO expression *) in + let* gas := (* TODO expression *) in + do* state.increment_nonce (| + env.["state"], + sender + |) in + let* sender_balance_after_gas_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + ethereum_types.numeric.U256 (| + sender_balance_after_gas_fee + |) + |) in + let* preaccessed_addresses := set (| + + |) in + let* preaccessed_storage_keys := set (| + + |) in + do* preaccessed_addresses.["add"] (| + env.["coinbase"] + |) in + (* TODO statement *) + let* message := utils.message.prepare_message (| + sender, + tx.["to"], + tx.["value"], + tx.["data"], + gas, + env + |) in + let* output := vm.interpreter.process_message_call (| + message, + env + |) in + let* gas_used := (* TODO expression *) in + let* gas_refund := min (| + (* TODO expression *), + ethereum_types.numeric.Uint (| + output.["refund_counter"] + |) + |) in + let* gas_refund_amount := (* TODO expression *) in + let* priority_fee_per_gas := (* TODO expression *) in + let* transaction_fee := (* TODO expression *) in + let* total_gas_used := (* TODO expression *) in + let* sender_balance_after_refund := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + sender_balance_after_refund + |) in + let* coinbase_balance_after_mining_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_transaction : M unit := + (* + 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 *) + + +Definition calculate_intrinsic_cost : M unit := + (* + 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. + *) + let* data_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + let* access_list_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + + +Definition recover_sender : M unit := + (* + 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 *) + + +Definition signing_hash_pre155 : M unit := + (* + 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 *) + + +Definition signing_hash_155 : M unit := + (* + 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 *) + + +Definition signing_hash_2930 : M unit := + (* + 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 *) + + +Definition signing_hash_1559 : M unit := + (* + 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 *) + + +Definition compute_header_hash : M unit := + (* + 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 *) + + +Definition check_gas_limit : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + 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..14de99d5e5 --- /dev/null +++ b/coq/ethereum/shanghai/fork_types.v @@ -0,0 +1,29 @@ +(* +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 ..crypto.hash. + +Definition encode_account : M unit := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + 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..2071b465c6 --- /dev/null +++ b/coq/ethereum/shanghai/state.v @@ -0,0 +1,585 @@ +(* +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 shanghai.blocks. +Require shanghai.fork_types. +Require shanghai.trie. + +Definition close_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 *) + + +Definition begin_transaction : 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* state.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + + +Definition commit_transaction : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* state.["_snapshots"].["pop"] (| + + |) in + (* TODO statement *) + + +Definition rollback_transaction : 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 *) + + +Definition get_account : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition get_account_optional : M unit := + (* + 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. + *) + let* account := trie.trie_get (| + state.["_main_trie"], + address + |) in + (* TODO statement *) + + +Definition set_account : 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 (| + state.["_main_trie"], + address, + account + |) in + + +Definition destroy_account : 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* destroy_storage (| + state, + address + |) in + do* set_account (| + state, + address, + (* TODO expression *) + |) in + + +Definition destroy_storage : 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 *) + + +Definition mark_account_created : 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* state.["created_accounts"].["add"] (| + address + |) in + + +Definition get_storage : M unit := + (* + 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. + *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_storage : 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 *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition storage_root : M unit := + (* + 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 *) + + +Definition state_root : M unit := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition account_exists : M unit := + (* + 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 *) + + +Definition account_has_code_or_nonce : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_empty : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition account_exists_and_is_empty : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_alive : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition modify_state : M unit := + (* + Modify an `Account` in the `State`. + *) + do* set_account (| + state, + address, + ethereum_types.frozen.modify (| + get_account (| + state, + address + |), + f + |) + |) in + + +Definition move_ether : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* modify_state (| + state, + sender_address, + reduce_sender_balance + |) in + do* modify_state (| + state, + recipient_address, + increase_recipient_balance + |) in + + +Definition process_withdrawal : M unit := + (* + Increase the balance of the withdrawing account. + *) + (* TODO statement *) + do* modify_state (| + state, + wd.["address"], + increase_recipient_balance + |) in + + +Definition set_account_balance : 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* modify_state (| + state, + address, + set_balance + |) in + + +Definition touch_account : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + + +Definition increment_nonce : 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* modify_state (| + state, + address, + increase_nonce + |) in + + +Definition set_code : 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* modify_state (| + state, + address, + write_code + |) in + + +Definition get_storage_original : M unit := + (* + 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 *) + let* original_account_trie := original_trie.["get"] (| + address + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + 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..ce1cb59b47 --- /dev/null +++ b/coq/ethereum/shanghai/transactions.v @@ -0,0 +1,27 @@ +(* +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 shanghai.exceptions. +Require shanghai.fork_types. + +Definition encode_transaction : M unit := + (* + Encode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + + +Definition decode_transaction : M unit := + (* + Decode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + 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..5f0ab29642 --- /dev/null +++ b/coq/ethereum/shanghai/trie.v @@ -0,0 +1,274 @@ +(* +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 : M unit := + (* + 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 *) + let* encoded := rlp.["encode"] (| + unencoded + |) in + (* TODO statement *) + + +Definition encode_node : M unit := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + + +Definition copy_trie : M unit := + (* + 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 *) + + +Definition trie_set : 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 *) + + +Definition trie_get : M unit := + (* + 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 *) + + +Definition common_prefix_length : M unit := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition nibble_list_to_compact : M unit := + (* + 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. + *) + let* compact := bytearray (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_nibble_list : M unit := + (* + 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. + *) + let* nibble_list := bytearray (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _prepare_trie : M unit := + (* + 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 *) + + +Definition root : M unit := + (* + 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. + *) + let* obj := _prepare_trie (| + trie, + get_storage_root + |) in + let* root_node := encode_internal_node (| + patricialize (| + obj, + Uint (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + + +Definition patricialize : M unit := + (* + 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 *) + let* arbitrary_key := next (| + iter (| + obj + |) + |) in + (* TODO statement *) + let* substring := (* TODO expression *) in + let* prefix_length := len (| + substring + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..beff4482b1 --- /dev/null +++ b/coq/ethereum/shanghai/utils/__init__.v @@ -0,0 +1,4 @@ +(* +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..1d6651723b --- /dev/null +++ b/coq/ethereum/shanghai/utils/address.v @@ -0,0 +1,99 @@ +(* +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 shanghai.fork_types. + +Definition to_address : M unit := + (* + 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 *) + + +Definition compute_contract_address : M unit := + (* + 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. + *) + let* computed_address := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *) + |) + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition compute_create2_contract_address : M unit := + (* + 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. + *) + let* preimage := (* TODO expression *) in + let* computed_address := ethereum.crypto.hash.keccak256 (| + preimage + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + 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..74a883654f --- /dev/null +++ b/coq/ethereum/shanghai/utils/hexadecimal.v @@ -0,0 +1,68 @@ +(* +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 shanghai.fork_types. + +Definition hex_to_root : M unit := + (* + 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 *) + + +Definition hex_to_bloom : M unit := + (* + 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 *) + + +Definition hex_to_address : M unit := + (* + 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 *) + 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..03aff15c2f --- /dev/null +++ b/coq/ethereum/shanghai/utils/message.v @@ -0,0 +1,82 @@ +(* +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 shanghai.fork_types. +Require shanghai.state. +Require shanghai.vm. +Require shanghai.vm.precompiled_contracts.mapping. +Require shanghai.utils.address. + +Definition prepare_message : M unit := + (* + 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 *) + let* accessed_addresses := set (| + + |) in + do* accessed_addresses.["add"] (| + current_target + |) in + do* accessed_addresses.["add"] (| + caller + |) in + do* accessed_addresses.["update"] (| + vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS.["keys"] (| + + |) + |) in + do* accessed_addresses.["update"] (| + preaccessed_addresses + |) in + (* TODO statement *) + 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..20d5165e4f --- /dev/null +++ b/coq/ethereum/shanghai/vm/__init__.v @@ -0,0 +1,69 @@ +(* +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 shanghai.blocks. +Require shanghai.fork_types. +Require shanghai.state. +Require shanghai.vm.precompiled_contracts. + +Definition incorporate_child_on_success : 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* evm.["accounts_to_delete"].["update"] (| + child_evm.["accounts_to_delete"] + |) in + do* evm.["touched_accounts"].["update"] (| + child_evm.["touched_accounts"] + |) in + (* TODO statement *) + do* evm.["accessed_addresses"].["update"] (| + child_evm.["accessed_addresses"] + |) in + do* evm.["accessed_storage_keys"].["update"] (| + child_evm.["accessed_storage_keys"] + |) in + + +Definition incorporate_child_on_error : 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 *) + (* TODO statement *) + 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..1784494410 --- /dev/null +++ b/coq/ethereum/shanghai/vm/exceptions.v @@ -0,0 +1,15 @@ +(* +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..6e166e3091 --- /dev/null +++ b/coq/ethereum/shanghai/vm/gas.v @@ -0,0 +1,170 @@ +(* +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 shanghai.vm.exceptions. + +Definition charge_gas : 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 (| + int (| + amount + |) + |) + |) in + (* TODO statement *) + + +Definition calculate_memory_gas_cost : M unit := + (* + 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. + *) + let* size_in_words := (* TODO expression *) in + let* linear_cost := (* TODO expression *) in + let* quadratic_cost := (* TODO expression *) in + let* total_gas_cost := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_gas_extend_memory : M unit := + (* + 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` + *) + let* size_to_extend := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* to_be_paid := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* current_size := ethereum_types.numeric.Uint (| + len (| + memory + |) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_message_call_gas : M unit := + (* + 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` + *) + let* call_stipend := (* TODO expression *) in + (* TODO statement *) + let* gas := min (| + gas, + max_message_call_gas (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + + +Definition max_message_call_gas : M unit := + (* + 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 *) + + +Definition init_code_cost : M unit := + (* + 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 *) + 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..b36b1ebfef --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/__init__.v @@ -0,0 +1,15 @@ +(* +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..a41f76b70d --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/arithmetic.v @@ -0,0 +1,387 @@ +(* +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 shanghai.vm.gas. +Require shanghai.vm.stack. + +Definition add : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_add"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition sub : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_sub"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mul : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + let* result := x.["wrapping_mul"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition div : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |) in + let* divisor := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + quotient + |) in + (* TODO statement *) + + +Definition sdiv : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* divisor := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + quotient + |) + |) in + (* TODO statement *) + + +Definition mod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + remainder + |) in + (* TODO statement *) + + +Definition smod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* y := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + remainder + |) + |) in + (* TODO statement *) + + +Definition addmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mulmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition exp : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* base := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent_bits := exponent.["bit_length"] (| + + |) in + let* exponent_bytes := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* result := ethereum_types.numeric.U256 (| + pow (| + base, + exponent, + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signextend : 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. + + *) + let* byte_num := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..29ee35e562 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/bitwise.v @@ -0,0 +1,245 @@ +(* +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 shanghai.vm.gas. +Require shanghai.vm.stack. + +Definition bitwise_and : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_or : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_xor : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_not : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition get_byte : 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. + + *) + let* byte_index := stack.pop (| + evm.["stack"] + |) in + let* word := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shl : 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. + *) + let* shift := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_shr : 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. + *) + let* shift := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition bitwise_sar : 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. + *) + let* shift := int (| + stack.pop (| + evm.["stack"] + |) + |) in + let* signed_value := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..f4a5ae1d9e --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/block.v @@ -0,0 +1,249 @@ +(* +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 shanghai.vm.gas. +Require shanghai.vm.stack. + +Definition block_hash : 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`. + *) + let* block_number := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOCK_HASH + |) in + let* max_block_number := (* TODO expression *) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + + +Definition coinbase : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["coinbase"] + |) + |) in + (* TODO statement *) + + +Definition timestamp : 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 (| + evm.["stack"], + evm.["env"].["time"] + |) in + (* TODO statement *) + + +Definition number : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["number"] + |) + |) in + (* TODO statement *) + + +Definition prev_randao : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["prev_randao"] + |) + |) in + (* TODO statement *) + + +Definition gas_limit : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_limit"] + |) + |) in + (* TODO statement *) + + +Definition chain_id : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["chain_id"] + |) + |) in + (* TODO statement *) + 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..3c0796c850 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/comparison.v @@ -0,0 +1,206 @@ +(* +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 shanghai.vm.gas. +Require shanghai.vm.stack. + +Definition less_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_less_than : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition greater_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_greater_than : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition equal : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition is_zero : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..d9f8f0e32d --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/control_flow.v @@ -0,0 +1,156 @@ +(* +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 shanghai.vm.gas. +Require shanghai.vm.exceptions. +Require shanghai.vm.stack. + +Definition stop : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition jump : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_MID + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition jumpi : 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. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* conditional_value := stack.pop (| + evm.["stack"] + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_HIGH + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition pc : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["pc"] + |) + |) in + (* TODO statement *) + + +Definition gas_left : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + + +Definition jumpdest : 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 *) + (* TODO statement *) + 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..08e53d2f4b --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/environment.v @@ -0,0 +1,568 @@ +(* +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 shanghai.fork_types. +Require shanghai.state. +Require shanghai.utils.address. +Require shanghai.vm.memory. +Require shanghai.vm.exceptions. +Require shanghai.vm.gas. +Require shanghai.vm.stack. + +Definition address : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["current_target"] + |) + |) in + (* TODO statement *) + + +Definition balance : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* balance := state.get_account (| + evm.["env"].["state"], + address + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition origin : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["origin"] + |) + |) in + (* TODO statement *) + + +Definition caller : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["caller"] + |) + |) in + (* TODO statement *) + + +Definition callvalue : 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 (| + evm.["stack"], + evm.["message"].["value"] + |) in + (* TODO statement *) + + +Definition calldataload : 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. + + *) + let* start_index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + start_index, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + value + |) + |) in + (* TODO statement *) + + +Definition calldatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["message"].["data"] + |) + |) + |) in + (* TODO statement *) + + +Definition calldatacopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* data_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + data_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition codesize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["code"] + |) + |) + |) in + (* TODO statement *) + + +Definition codecopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["code"], + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition gasprice : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_price"] + |) + |) in + (* TODO statement *) + + +Definition extcodesize : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* codesize := ethereum_types.numeric.U256 (| + len (| + state.get_account (| + evm.["env"].["state"], + address + |).["code"] + |) + |) in + do* stack.push (| + evm.["stack"], + codesize + |) in + (* TODO statement *) + + +Definition extcodecopy : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* code := state.get_account (| + evm.["env"].["state"], + address + |).["code"] in + let* value := vm.memory.buffer_read (| + code, + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition returndatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["return_data"] + |) + |) + |) in + (* TODO statement *) + + +Definition returndatacopy : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* return_data_start_position := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition extcodehash : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + (* TODO statement *) + let* account := state.get_account (| + evm.["env"].["state"], + address + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + codehash + |) in + (* TODO statement *) + + +Definition self_balance : 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 + let* balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition base_fee : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["base_fee_per_gas"] + |) + |) in + (* TODO statement *) + 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..47aeac27c2 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/keccak.v @@ -0,0 +1,67 @@ +(* +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 shanghai.vm.gas. +Require shanghai.vm.memory. +Require shanghai.vm.stack. + +Definition keccak : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* word_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + let* hash := ethereum.crypto.hash.keccak256 (| + data + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + 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..4fff4c4261 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/log.v @@ -0,0 +1,61 @@ +(* +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 shanghai.blocks. +Require shanghai.vm.exceptions. +Require shanghai.vm.gas. +Require shanghai.vm.memory. +Require shanghai.vm.stack. + +Definition log_n : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* topics := (* TODO expression *) in + (* TODO statement *) + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* log_entry := blocks.Log (| + + |) in + (* TODO assignment *) + (* TODO statement *) + 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..bec982f2ff --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/memory.v @@ -0,0 +1,158 @@ +(* +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 shanghai.vm.gas. +Require shanghai.vm.memory. +Require shanghai.vm.stack. + +Definition mstore : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* memory.memory_write (| + evm.["memory"], + start_position, + value + |) in + (* TODO statement *) + + +Definition mstore8 : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + (* TODO expression *) + |) in + do* memory.memory_write (| + evm.["memory"], + start_position, + normalized_bytes_value + |) in + (* TODO statement *) + + +Definition mload : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.memory_read_bytes (| + evm.["memory"], + start_position, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition msize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["memory"] + |) + |) + |) in + (* TODO statement *) + 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..24ccc6f94b --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/stack.v @@ -0,0 +1,130 @@ +(* +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 shanghai.vm.exceptions. +Require shanghai.vm.gas. +Require shanghai.vm.memory. + +Definition pop : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* stack.["pop"] (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BASE + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition push_n : 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 *) + let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + evm.["code"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + num_bytes + |) + |) + |) in + do* stack.["push"] (| + evm.["stack"], + data_to_push + |) in + (* TODO statement *) + + +Definition dup_n : 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 *) + let* data_to_duplicate := (* TODO expression *) in + do* stack.["push"] (| + evm.["stack"], + data_to_duplicate + |) in + (* TODO statement *) + + +Definition swap_n : 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 *) + (* TODO statement *) + 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..e65584a478 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/storage.v @@ -0,0 +1,97 @@ +(* +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 shanghai.state. +Require shanghai.vm.exceptions. +Require shanghai.vm.gas. +Require shanghai.vm.stack. + +Definition sload : 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. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + (* TODO statement *) + let* value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition sstore : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + (* TODO statement *) + let* original_value := state.get_storage_original (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + let* current_value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + let* gas_cost := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + do* state.set_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + 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..e0695c9e7e --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/system.v @@ -0,0 +1,598 @@ +(* +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 shanghai.fork_types. +Require shanghai.state. +Require shanghai.utils.address. +Require shanghai.vm.exceptions. +Require shanghai.vm.gas. +Require shanghai.vm.memory. +Require shanghai.vm.stack. + +Definition generic_create : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) in + (* TODO statement *) + do* evm.["accessed_addresses"].["add"] (| + contract_address + |) in + let* create_message_gas := gas.max_message_call_gas (| + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + let* sender_address := evm.["message"].["current_target"] in + let* sender := state.get_account (| + evm.["env"].["state"], + sender_address + |) in + (* TODO statement *) + (* TODO statement *) + do* state.increment_nonce (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |) in + let* child_message := Message (| + + |) in + let* child_evm := process_create_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + + +Definition create : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* init_code_gas := gas.init_code_cost (| + ethereum_types.numeric.Uint (| + memory_size + |) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_contract_address (| + evm.["message"].["current_target"], + state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["nonce"] + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size, + init_code_gas + |) in + (* TODO statement *) + + +Definition create2 : 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. + *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* salt := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* call_data_words := (* TODO expression *) in + let* init_code_gas := gas.init_code_cost (| + ethereum_types.numeric.Uint (| + memory_size + |) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* contract_address := utils.address.compute_create2_contract_address (| + evm.["message"].["current_target"], + salt, + memory.memory_read_bytes (| + evm.["memory"], + memory_start_position, + memory_size + |) + |) in + do* generic_create (| + evm, + endowment, + contract_address, + memory_start_position, + memory_size, + init_code_gas + |) in + (* TODO statement *) + + +Definition return_ : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + + +Definition generic_call : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_input_start_position, + memory_input_size + |) in + let* code := state.get_account (| + evm.["env"].["state"], + code_address + |).["code"] in + let* child_message := Message (| + + |) in + let* child_evm := process_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + let* actual_output_size := min (| + memory_output_size, + ethereum_types.numeric.U256 (| + len (| + child_evm.["output"] + |) + |) + |) in + do* memory.memory_write (| + evm.["memory"], + memory_output_start_position, + (* TODO expression *) + |) in + + +Definition call : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* create_gas_cost := (* TODO expression *) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition callcode : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* to := evm.["message"].["current_target"] in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition selfdestruct : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* beneficiary := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* gas_cost := gas.GAS_SELF_DESTRUCT in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + (* TODO statement *) + let* originator := evm.["message"].["current_target"] in + let* beneficiary_balance := state.get_account (| + evm.["env"].["state"], + beneficiary + |).["balance"] in + let* originator_balance := state.get_account (| + evm.["env"].["state"], + originator + |).["balance"] in + do* state.set_account_balance (| + evm.["env"].["state"], + beneficiary, + (* TODO expression *) + |) in + do* state.set_account_balance (| + evm.["env"].["state"], + originator, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* evm.["accounts_to_delete"].["add"] (| + originator + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition delegatecall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + access_gas_cost + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + evm.["message"].["value"], + evm.["message"].["caller"], + evm.["message"].["current_target"], + code_address, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition staticcall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + (* TODO statement *) + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + access_gas_cost + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + evm.["message"].["current_target"], + to, + to, + (* TODO expression *), + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + + +Definition revert : 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. + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + extend_memory.["cost"] + |) in + (* TODO statement *) + let* output := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + 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..03268f520c --- /dev/null +++ b/coq/ethereum/shanghai/vm/interpreter.v @@ -0,0 +1,159 @@ +(* +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 shanghai.blocks. +Require shanghai.fork_types. +Require shanghai.state. +Require shanghai.vm. +Require shanghai.vm.gas. +Require shanghai.vm.precompiled_contracts.mapping. +Require shanghai.vm.exceptions. +Require shanghai.vm.instructions. +Require shanghai.vm.runtime. + +Definition process_message_call : M unit := + (* + 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 *) + let* tx_end := ethereum.trace.TransactionEnd (| + (* TODO expression *), + evm.["output"], + evm.["error"] + |) in + do* ethereum.trace.evm_trace (| + evm, + tx_end + |) in + (* TODO statement *) + + +Definition process_create_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.destroy_storage (| + env.["state"], + message.["current_target"] + |) in + do* state.mark_account_created (| + env.["state"], + message.["current_target"] + |) in + do* state.increment_nonce (| + env.["state"], + message.["current_target"] + |) in + let* evm := process_message (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.touch_account (| + env.["state"], + message.["current_target"] + |) in + (* TODO statement *) + let* evm := execute_code (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition execute_code : M unit := + (* + 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 + *) + let* code := message.["code"] in + let* valid_jump_destinations := runtime.get_valid_jump_destinations (| + code + |) in + let* evm := Evm (| + + |) in + (* TODO statement *) + (* TODO statement *) + 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..94b6a44639 --- /dev/null +++ b/coq/ethereum/shanghai/vm/memory.v @@ -0,0 +1,75 @@ +(* +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 : 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 *) + + +Definition memory_read_bytes : M unit := + (* + 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 *) + + +Definition buffer_read : M unit := + (* + 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 *) + 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..529f15525e --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/__init__.v @@ -0,0 +1,16 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require 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..d07cfa8502 --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,187 @@ +(* +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 shanghai.vm. +Require shanghai.vm.gas. +Require shanghai.vm.memory. +Require shanghai.vm.exceptions. + +Definition alt_bn128_add : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* x1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x1_bytes + |) + |) in + let* y1_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y1_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y1_bytes + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := (* TODO expression *) in + (* TODO assignment *) + + +Definition alt_bn128_mul : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + let* x0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* x0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + x0_bytes + |) + |) in + let* y0_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* y0_value := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + y0_bytes + |) + |) in + let* n := int (| + ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* p := p0.["mul_by"] (| + n + |) in + (* TODO assignment *) + + +Definition alt_bn128_pairing_check : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + ethereum_types.numeric.Uint (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..29e808fc5d --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,41 @@ +(* +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 shanghai.vm. +Require shanghai.vm.gas. +Require shanghai.vm.exceptions. + +Definition blake2f : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + (* TODO statement *) + let* blake2b := ethereum.crypto.blake2.Blake2b (| + + |) in + (* TODO assignment *) + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + 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..c1bf9ed28f --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,93 @@ +(* +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 shanghai.vm. +Require shanghai.vm.gas. +Require shanghai.vm.memory. + +Definition ecrecover : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_ECRECOVER + |) in + let* message_hash_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* message_hash := ethereum.crypto.hash.Hash32 (| + message_hash_bytes + |) in + let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + address, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..24644930d5 --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/identity.v @@ -0,0 +1,36 @@ +(* +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 shanghai.vm. +Require shanghai.vm.gas. + +Definition identity : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..55121afa47 --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/mapping.v @@ -0,0 +1,23 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require shanghai.fork_types. +Require shanghai.vm.precompiled_contracts.alt_bn128. +Require shanghai.vm.precompiled_contracts.blake2f. +Require shanghai.vm.precompiled_contracts.ecrecover. +Require shanghai.vm.precompiled_contracts.identity. +Require shanghai.vm.precompiled_contracts.modexp. +Require shanghai.vm.precompiled_contracts.ripemd160. +Require 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..9710ce4e6f --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/modexp.v @@ -0,0 +1,203 @@ +(* +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 shanghai.vm. +Require shanghai.vm.gas. +Require shanghai.vm.memory. + +Definition modexp : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + let* data := evm.["message"].["data"] in + let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* exp_start := (* TODO expression *) in + let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + min (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + exp_length + |) + |) + |) in + do* vm.gas.charge_gas (| + evm, + gas_cost (| + base_length, + modulus_length, + exp_length, + exp_head + |) + |) in + (* TODO statement *) + let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + base_length + |) + |) in + let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + exp_start, + exp_length + |) + |) in + let* modulus_start := (* TODO expression *) in + let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| + memory.buffer_read (| + data, + modulus_start, + modulus_length + |) + |) in + (* TODO statement *) + + +Definition complexity : M unit := + (* + 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. + *) + let* max_length := max (| + ethereum_types.numeric.Uint (| + base_length + |), + ethereum_types.numeric.Uint (| + modulus_length + |) + |) in + let* words := (* TODO expression *) in + (* TODO statement *) + + +Definition iterations : M unit := + (* + 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 *) + + +Definition gas_cost : M unit := + (* + 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. + *) + let* multiplication_complexity := complexity (| + base_length, + modulus_length + |) in + let* iteration_count := iterations (| + exponent_length, + exponent_head + |) in + let* cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..bc5e73dd3c --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,42 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + let* hash_bytes := hashlib.["new"] (| + (* TODO expression *), + data + |).["digest"] (| + + |) in + let* padded_hash := left_pad_zero_bytes (| + hash_bytes, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..da6972d411 --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/sha256.v @@ -0,0 +1,32 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..734dcebd63 --- /dev/null +++ b/coq/ethereum/shanghai/vm/runtime.v @@ -0,0 +1,49 @@ +(* +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 shanghai.vm.instructions. + +Definition get_valid_jump_destinations : M unit := + (* + 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. + *) + let* valid_jump_destinations := set (| + + |) in + let* pc := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..bf9f5adca8 --- /dev/null +++ b/coq/ethereum/shanghai/vm/stack.v @@ -0,0 +1,53 @@ +(* +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 shanghai.vm.exceptions. + +Definition pop : M unit := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + + +Definition push : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + 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..9dc9482bb6 --- /dev/null +++ b/coq/ethereum/spurious_dragon/__init__.v @@ -0,0 +1,9 @@ +(* +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..88505e0073 --- /dev/null +++ b/coq/ethereum/spurious_dragon/blocks.v @@ -0,0 +1,19 @@ +(* +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 ..crypto.hash. +Require spurious_dragon.fork_types. +Require 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..878994ceca --- /dev/null +++ b/coq/ethereum/spurious_dragon/bloom.v @@ -0,0 +1,66 @@ +(* +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 spurious_dragon.blocks. +Require spurious_dragon.fork_types. + +Definition add_to_bloom : 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. + *) + let* hash := ethereum.crypto.hash.keccak256 (| + bloom_entry + |) in + (* TODO statement *) + + +Definition logs_bloom : M unit := + (* + 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 *) + 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..1c4f301633 --- /dev/null +++ b/coq/ethereum/spurious_dragon/fork.v @@ -0,0 +1,756 @@ +(* +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 spurious_dragon.blocks. +Require spurious_dragon.bloom. +Require spurious_dragon.fork_types. +Require spurious_dragon.state. +Require spurious_dragon.transactions. +Require spurious_dragon.trie. +Require spurious_dragon.utils.message. +Require spurious_dragon.vm.interpreter. + +Definition apply_fork : M unit := + (* + 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 *) + + +Definition get_last_256_block_hashes : M unit := + (* + 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. + *) + let* recent_blocks := (* TODO expression *) in + (* TODO statement *) + let* recent_block_hashes := (* TODO expression *) in + (* TODO statement *) + let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *).["header"] + |) + |) in + do* recent_block_hashes.["append"] (| + most_recent_block_hash + |) in + (* TODO statement *) + + +Definition state_transition : 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`. + *) + let* parent_header := (* TODO expression *).["header"] in + do* validate_header (| + block.["header"], + parent_header + |) in + do* validate_ommers (| + block.["ommers"], + block.["header"], + chain + |) in + let* apply_body_output := apply_body (| + chain.["state"], + get_last_256_block_hashes (| + chain + |), + block.["header"].["coinbase"], + block.["header"].["number"], + block.["header"].["gas_limit"], + block.["header"].["timestamp"], + block.["header"].["difficulty"], + block.["transactions"], + block.["ommers"], + chain.["chain_id"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* chain.["blocks"].["append"] (| + block + |) in + (* TODO statement *) + + +Definition validate_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 *) + let* block_difficulty := calculate_block_difficulty (| + header.["number"], + header.["timestamp"], + parent_header.["timestamp"], + parent_header.["difficulty"] + |) in + (* TODO statement *) + let* block_parent_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + parent_header + |) + |) in + (* TODO statement *) + do* validate_proof_of_work (| + header + |) in + + +Definition generate_header_hash_for_pow : M unit := + (* + 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. + *) + let* header_data_without_pow_artefacts := (* TODO expression *) in + (* TODO statement *) + + +Definition validate_proof_of_work : 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. + *) + let* header_hash := generate_header_hash_for_pow (| + header + |) in + let* cache := ethereum.ethash.generate_cache (| + header.["number"] + |) in + (* TODO assignment *) + (* TODO statement *) + let* limit := (* TODO expression *) in + (* TODO statement *) + + +Definition check_transaction : M unit := + (* + 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 *) + let* sender_address := recover_sender (| + chain_id, + tx + |) in + (* TODO statement *) + + +Definition make_receipt : M unit := + (* + 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. + *) + let* receipt := blocks.Receipt (| + + |) in + (* TODO statement *) + + +Definition apply_body : M unit := + (* + 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. + *) + let* gas_available := block_gas_limit in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* pay_rewards (| + state, + block_number, + coinbase, + ommers + |) in + let* block_gas_used := (* TODO expression *) in + let* block_logs_bloom := bloom.logs_bloom (| + block_logs + |) in + (* TODO statement *) + + +Definition validate_ommers : 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. + *) + let* block_hash := rlp.["rlp_hash"] (| + block_header + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* ommers_hashes := (* TODO expression *) in + (* TODO statement *) + let* recent_canonical_blocks := (* TODO expression *) in + let* recent_canonical_block_hashes := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition pay_rewards : 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. + *) + let* ommer_count := ethereum_types.numeric.U256 (| + len (| + ommers + |) + |) in + let* miner_reward := (* TODO expression *) in + do* state.create_ether (| + state, + coinbase, + miner_reward + |) in + (* TODO statement *) + + +Definition process_transaction : M unit := + (* + 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 *) + let* sender := env.["origin"] in + let* sender_account := state.get_account (| + env.["state"], + sender + |) in + let* gas_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* gas := (* TODO expression *) in + do* state.increment_nonce (| + env.["state"], + sender + |) in + let* sender_balance_after_gas_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + ethereum_types.numeric.U256 (| + sender_balance_after_gas_fee + |) + |) in + let* message := utils.message.prepare_message (| + sender, + tx.["to"], + tx.["value"], + tx.["data"], + gas, + env + |) in + let* output := vm.interpreter.process_message_call (| + message, + env + |) in + let* gas_used := (* TODO expression *) in + let* gas_refund := min (| + (* TODO expression *), + ethereum_types.numeric.Uint (| + output.["refund_counter"] + |) + |) in + let* gas_refund_amount := (* TODO expression *) in + let* transaction_fee := (* TODO expression *) in + let* total_gas_used := (* TODO expression *) in + let* sender_balance_after_refund := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + sender_balance_after_refund + |) in + let* coinbase_balance_after_mining_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition validate_transaction : M unit := + (* + 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 *) + + +Definition calculate_intrinsic_cost : M unit := + (* + 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. + *) + let* data_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition recover_sender : M unit := + (* + 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 *) + + +Definition signing_hash_pre155 : M unit := + (* + 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 *) + + +Definition signing_hash_155 : M unit := + (* + 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 *) + + +Definition compute_header_hash : M unit := + (* + 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 *) + + +Definition check_gas_limit : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_block_difficulty : M unit := + (* + 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. + *) + let* offset := (* TODO expression *) in + let* difficulty := (* TODO expression *) in + let* num_bomb_periods := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..14de99d5e5 --- /dev/null +++ b/coq/ethereum/spurious_dragon/fork_types.v @@ -0,0 +1,29 @@ +(* +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 ..crypto.hash. + +Definition encode_account : M unit := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + 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..1eb8a64d70 --- /dev/null +++ b/coq/ethereum/spurious_dragon/state.v @@ -0,0 +1,543 @@ +(* +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 spurious_dragon.fork_types. +Require spurious_dragon.trie. + +Definition close_state : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition begin_transaction : 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* state.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + + +Definition commit_transaction : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* state.["_snapshots"].["pop"] (| + + |) in + + +Definition rollback_transaction : 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 *) + + +Definition get_account : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition get_account_optional : M unit := + (* + 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. + *) + let* account := trie.trie_get (| + state.["_main_trie"], + address + |) in + (* TODO statement *) + + +Definition set_account : 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 (| + state.["_main_trie"], + address, + account + |) in + + +Definition destroy_account : 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* destroy_storage (| + state, + address + |) in + do* set_account (| + state, + address, + (* TODO expression *) + |) in + + +Definition destroy_storage : 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 *) + + +Definition get_storage : M unit := + (* + 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. + *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_storage : 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 *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition storage_root : M unit := + (* + 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 *) + + +Definition state_root : M unit := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition account_exists : M unit := + (* + 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 *) + + +Definition account_has_code_or_nonce : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_empty : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition account_exists_and_is_empty : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition is_account_alive : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition modify_state : M unit := + (* + Modify an `Account` in the `State`. + *) + do* set_account (| + state, + address, + ethereum_types.frozen.modify (| + get_account (| + state, + address + |), + f + |) + |) in + + +Definition move_ether : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* modify_state (| + state, + sender_address, + reduce_sender_balance + |) in + do* modify_state (| + state, + recipient_address, + increase_recipient_balance + |) in + + +Definition set_account_balance : 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* modify_state (| + state, + address, + set_balance + |) in + + +Definition touch_account : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + + +Definition increment_nonce : 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* modify_state (| + state, + address, + increase_nonce + |) in + + +Definition set_code : 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* modify_state (| + state, + address, + write_code + |) in + + +Definition create_ether : 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* modify_state (| + state, + address, + increase_balance + |) in + 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..d9f9943d88 --- /dev/null +++ b/coq/ethereum/spurious_dragon/transactions.v @@ -0,0 +1,12 @@ +(* +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 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..5f0ab29642 --- /dev/null +++ b/coq/ethereum/spurious_dragon/trie.v @@ -0,0 +1,274 @@ +(* +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 : M unit := + (* + 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 *) + let* encoded := rlp.["encode"] (| + unencoded + |) in + (* TODO statement *) + + +Definition encode_node : M unit := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + + +Definition copy_trie : M unit := + (* + 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 *) + + +Definition trie_set : 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 *) + + +Definition trie_get : M unit := + (* + 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 *) + + +Definition common_prefix_length : M unit := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition nibble_list_to_compact : M unit := + (* + 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. + *) + let* compact := bytearray (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_nibble_list : M unit := + (* + 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. + *) + let* nibble_list := bytearray (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _prepare_trie : M unit := + (* + 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 *) + + +Definition root : M unit := + (* + 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. + *) + let* obj := _prepare_trie (| + trie, + get_storage_root + |) in + let* root_node := encode_internal_node (| + patricialize (| + obj, + Uint (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + + +Definition patricialize : M unit := + (* + 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 *) + let* arbitrary_key := next (| + iter (| + obj + |) + |) in + (* TODO statement *) + let* substring := (* TODO expression *) in + let* prefix_length := len (| + substring + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..beff4482b1 --- /dev/null +++ b/coq/ethereum/spurious_dragon/utils/__init__.v @@ -0,0 +1,4 @@ +(* +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..de189a64ef --- /dev/null +++ b/coq/ethereum/spurious_dragon/utils/address.v @@ -0,0 +1,67 @@ +(* +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 spurious_dragon.fork_types. + +Definition to_address : M unit := + (* + 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 *) + + +Definition compute_contract_address : M unit := + (* + 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. + *) + let* computed_address := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *) + |) + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + 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..6a6aeb82fb --- /dev/null +++ b/coq/ethereum/spurious_dragon/utils/hexadecimal.v @@ -0,0 +1,68 @@ +(* +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 spurious_dragon.fork_types. + +Definition hex_to_root : M unit := + (* + 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 *) + + +Definition hex_to_bloom : M unit := + (* + 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 *) + + +Definition hex_to_address : M unit := + (* + 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 *) + 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..e2397508c4 --- /dev/null +++ b/coq/ethereum/spurious_dragon/utils/message.v @@ -0,0 +1,56 @@ +(* +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 spurious_dragon.fork_types. +Require spurious_dragon.state. +Require spurious_dragon.vm. +Require spurious_dragon.utils.address. + +Definition prepare_message : M unit := + (* + 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 *) + 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..995a573d09 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/__init__.v @@ -0,0 +1,63 @@ +(* +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 spurious_dragon.blocks. +Require spurious_dragon.fork_types. +Require spurious_dragon.state. +Require spurious_dragon.vm.precompiled_contracts. + +Definition incorporate_child_on_success : 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* evm.["accounts_to_delete"].["update"] (| + child_evm.["accounts_to_delete"] + |) in + do* evm.["touched_accounts"].["update"] (| + child_evm.["touched_accounts"] + |) in + (* TODO statement *) + + +Definition incorporate_child_on_error : 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 *) + (* TODO statement *) + 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..1784494410 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/exceptions.v @@ -0,0 +1,15 @@ +(* +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..f4e13617c8 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/gas.v @@ -0,0 +1,151 @@ +(* +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 spurious_dragon.vm.exceptions. + +Definition charge_gas : 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 (| + int (| + amount + |) + |) + |) in + (* TODO statement *) + + +Definition calculate_memory_gas_cost : M unit := + (* + 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. + *) + let* size_in_words := (* TODO expression *) in + let* linear_cost := (* TODO expression *) in + let* quadratic_cost := (* TODO expression *) in + let* total_gas_cost := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_gas_extend_memory : M unit := + (* + 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` + *) + let* size_to_extend := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* to_be_paid := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* current_size := ethereum_types.numeric.Uint (| + len (| + memory + |) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_message_call_gas : M unit := + (* + 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` + *) + let* call_stipend := (* TODO expression *) in + (* TODO statement *) + let* gas := min (| + gas, + max_message_call_gas (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + + +Definition max_message_call_gas : M unit := + (* + 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 *) + 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..b36b1ebfef --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/__init__.v @@ -0,0 +1,15 @@ +(* +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..1fafedb5e9 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/arithmetic.v @@ -0,0 +1,387 @@ +(* +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 spurious_dragon.vm.gas. +Require spurious_dragon.vm.stack. + +Definition add : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_add"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition sub : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_sub"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mul : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + let* result := x.["wrapping_mul"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition div : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |) in + let* divisor := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + quotient + |) in + (* TODO statement *) + + +Definition sdiv : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* divisor := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + quotient + |) + |) in + (* TODO statement *) + + +Definition mod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + remainder + |) in + (* TODO statement *) + + +Definition smod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* y := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + remainder + |) + |) in + (* TODO statement *) + + +Definition addmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mulmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition exp : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* base := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent_bits := exponent.["bit_length"] (| + + |) in + let* exponent_bytes := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* result := ethereum_types.numeric.U256 (| + pow (| + base, + exponent, + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signextend : 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. + + *) + let* byte_num := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..b8fa64fff5 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/bitwise.v @@ -0,0 +1,156 @@ +(* +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 spurious_dragon.vm.gas. +Require spurious_dragon.vm.stack. + +Definition bitwise_and : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_or : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_xor : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_not : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition get_byte : 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. + + *) + let* byte_index := stack.pop (| + evm.["stack"] + |) in + let* word := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..bf55cc4aa6 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/block.v @@ -0,0 +1,183 @@ +(* +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 spurious_dragon.vm.gas. +Require spurious_dragon.vm.stack. + +Definition block_hash : 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. + + *) + let* block_number := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOCK_HASH + |) in + let* max_block_number := (* TODO expression *) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + + +Definition coinbase : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["coinbase"] + |) + |) in + (* TODO statement *) + + +Definition timestamp : 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 (| + evm.["stack"], + evm.["env"].["time"] + |) in + (* TODO statement *) + + +Definition number : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["number"] + |) + |) in + (* TODO statement *) + + +Definition difficulty : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["difficulty"] + |) + |) in + (* TODO statement *) + + +Definition gas_limit : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_limit"] + |) + |) in + (* TODO statement *) + 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..574749ebac --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/comparison.v @@ -0,0 +1,206 @@ +(* +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 spurious_dragon.vm.gas. +Require spurious_dragon.vm.stack. + +Definition less_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_less_than : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition greater_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_greater_than : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition equal : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition is_zero : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..f3652fcd26 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/control_flow.v @@ -0,0 +1,156 @@ +(* +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 spurious_dragon.vm.gas. +Require spurious_dragon.vm.exceptions. +Require spurious_dragon.vm.stack. + +Definition stop : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition jump : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_MID + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition jumpi : 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. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* conditional_value := stack.pop (| + evm.["stack"] + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_HIGH + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition pc : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["pc"] + |) + |) in + (* TODO statement *) + + +Definition gas_left : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + + +Definition jumpdest : 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 *) + (* TODO statement *) + 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..fdc679afce --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/environment.v @@ -0,0 +1,434 @@ +(* +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 spurious_dragon.state. +Require spurious_dragon.utils.address. +Require spurious_dragon.vm.memory. +Require spurious_dragon.vm.gas. +Require spurious_dragon.vm.stack. + +Definition address : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["current_target"] + |) + |) in + (* TODO statement *) + + +Definition balance : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BALANCE + |) in + let* balance := state.get_account (| + evm.["env"].["state"], + address + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition origin : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["origin"] + |) + |) in + (* TODO statement *) + + +Definition caller : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["caller"] + |) + |) in + (* TODO statement *) + + +Definition callvalue : 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 (| + evm.["stack"], + evm.["message"].["value"] + |) in + (* TODO statement *) + + +Definition calldataload : 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. + + *) + let* start_index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + start_index, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + value + |) + |) in + (* TODO statement *) + + +Definition calldatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["message"].["data"] + |) + |) + |) in + (* TODO statement *) + + +Definition calldatacopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* data_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + data_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition codesize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["code"] + |) + |) + |) in + (* TODO statement *) + + +Definition codecopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["code"], + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition gasprice : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_price"] + |) + |) in + (* TODO statement *) + + +Definition extcodesize : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_EXTERNAL + |) in + let* codesize := ethereum_types.numeric.U256 (| + len (| + state.get_account (| + evm.["env"].["state"], + address + |).["code"] + |) + |) in + do* stack.push (| + evm.["stack"], + codesize + |) in + (* TODO statement *) + + +Definition extcodecopy : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* code := state.get_account (| + evm.["env"].["state"], + address + |).["code"] in + let* value := vm.memory.buffer_read (| + code, + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + 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..4c744eefe2 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/keccak.v @@ -0,0 +1,67 @@ +(* +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 spurious_dragon.vm.gas. +Require spurious_dragon.vm.memory. +Require spurious_dragon.vm.stack. + +Definition keccak : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* word_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + let* hash := ethereum.crypto.hash.keccak256 (| + data + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + 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..3a5126b702 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/log.v @@ -0,0 +1,59 @@ +(* +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 spurious_dragon.blocks. +Require spurious_dragon.vm.gas. +Require spurious_dragon.vm.memory. +Require spurious_dragon.vm.stack. + +Definition log_n : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* topics := (* TODO expression *) in + (* TODO statement *) + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* log_entry := blocks.Log (| + + |) in + (* TODO assignment *) + (* TODO statement *) + 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..128b299841 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/memory.v @@ -0,0 +1,158 @@ +(* +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 spurious_dragon.vm.gas. +Require spurious_dragon.vm.memory. +Require spurious_dragon.vm.stack. + +Definition mstore : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* memory.memory_write (| + evm.["memory"], + start_position, + value + |) in + (* TODO statement *) + + +Definition mstore8 : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + (* TODO expression *) + |) in + do* memory.memory_write (| + evm.["memory"], + start_position, + normalized_bytes_value + |) in + (* TODO statement *) + + +Definition mload : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.memory_read_bytes (| + evm.["memory"], + start_position, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition msize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["memory"] + |) + |) + |) in + (* TODO statement *) + 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..5c85c4ed9e --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/stack.v @@ -0,0 +1,133 @@ +(* +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 spurious_dragon.vm.exceptions. +Require spurious_dragon.vm.gas. +Require spurious_dragon.vm.memory. + +Definition pop : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* stack.["pop"] (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BASE + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition push_n : 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 + let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + evm.["code"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + num_bytes + |) + |) + |) in + do* stack.["push"] (| + evm.["stack"], + data_to_push + |) in + (* TODO statement *) + + +Definition dup_n : 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 *) + let* data_to_duplicate := (* TODO expression *) in + do* stack.["push"] (| + evm.["stack"], + data_to_duplicate + |) in + (* TODO statement *) + + +Definition swap_n : 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 *) + (* TODO statement *) + 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..77a9c099d2 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/storage.v @@ -0,0 +1,88 @@ +(* +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 spurious_dragon.state. +Require spurious_dragon.vm.gas. +Require spurious_dragon.vm.stack. + +Definition sload : 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. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_SLOAD + |) in + let* value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition sstore : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + let* current_value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + do* state.set_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + 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..27d5f37875 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/system.v @@ -0,0 +1,383 @@ +(* +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 spurious_dragon.fork_types. +Require spurious_dragon.state. +Require spurious_dragon.utils.address. +Require spurious_dragon.vm.gas. +Require spurious_dragon.vm.memory. +Require spurious_dragon.vm.stack. + +Definition create : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* create_message_gas := gas.max_message_call_gas (| + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* sender_address := evm.["message"].["current_target"] in + let* sender := state.get_account (| + evm.["env"].["state"], + sender_address + |) in + let* contract_address := utils.address.compute_contract_address (| + evm.["message"].["current_target"], + state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["nonce"] + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition return_ : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + + +Definition generic_call : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_input_start_position, + memory_input_size + |) in + let* code := state.get_account (| + evm.["env"].["state"], + code_address + |).["code"] in + let* child_message := Message (| + + |) in + let* child_evm := process_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + let* actual_output_size := min (| + memory_output_size, + ethereum_types.numeric.U256 (| + len (| + child_evm.["output"] + |) + |) + |) in + do* memory.memory_write (| + evm.["memory"], + memory_output_start_position, + (* TODO expression *) + |) in + + +Definition call : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* create_gas_cost := (* TODO expression *) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition callcode : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* to := evm.["message"].["current_target"] in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition selfdestruct : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* beneficiary := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* gas_cost := gas.GAS_SELF_DESTRUCT in + (* TODO statement *) + let* originator := evm.["message"].["current_target"] in + let* refunded_accounts := evm.["accounts_to_delete"] in + let* parent_evm := evm.["message"].["parent_evm"] in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + let* beneficiary_balance := state.get_account (| + evm.["env"].["state"], + beneficiary + |).["balance"] in + let* originator_balance := state.get_account (| + evm.["env"].["state"], + originator + |).["balance"] in + do* state.set_account_balance (| + evm.["env"].["state"], + beneficiary, + (* TODO expression *) + |) in + do* state.set_account_balance (| + evm.["env"].["state"], + originator, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* evm.["accounts_to_delete"].["add"] (| + originator + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition delegatecall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + gas.GAS_CALL + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + evm.["message"].["value"], + evm.["message"].["caller"], + evm.["message"].["current_target"], + code_address, + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + 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..f3eec05c02 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/interpreter.v @@ -0,0 +1,155 @@ +(* +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 spurious_dragon.blocks. +Require spurious_dragon.fork_types. +Require spurious_dragon.state. +Require spurious_dragon.vm. +Require spurious_dragon.vm.gas. +Require spurious_dragon.vm.precompiled_contracts.mapping. +Require spurious_dragon.vm.exceptions. +Require spurious_dragon.vm.instructions. +Require spurious_dragon.vm.runtime. + +Definition process_message_call : M unit := + (* + 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 *) + let* tx_end := ethereum.trace.TransactionEnd (| + (* TODO expression *), + evm.["output"], + evm.["error"] + |) in + do* ethereum.trace.evm_trace (| + evm, + tx_end + |) in + (* TODO statement *) + + +Definition process_create_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.destroy_storage (| + env.["state"], + message.["current_target"] + |) in + do* state.increment_nonce (| + env.["state"], + message.["current_target"] + |) in + let* evm := process_message (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.touch_account (| + env.["state"], + message.["current_target"] + |) in + (* TODO statement *) + let* evm := execute_code (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition execute_code : M unit := + (* + 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 + *) + let* code := message.["code"] in + let* valid_jump_destinations := runtime.get_valid_jump_destinations (| + code + |) in + let* evm := Evm (| + + |) in + (* TODO statement *) + (* TODO statement *) + 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..94b6a44639 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/memory.v @@ -0,0 +1,75 @@ +(* +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 : 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 *) + + +Definition memory_read_bytes : M unit := + (* + 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 *) + + +Definition buffer_read : M unit := + (* + 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 *) + 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..3f74475666 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.v @@ -0,0 +1,16 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require 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..b59ea16dbe --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,93 @@ +(* +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 spurious_dragon.vm. +Require spurious_dragon.vm.gas. +Require spurious_dragon.vm.memory. + +Definition ecrecover : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_ECRECOVER + |) in + let* message_hash_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* message_hash := ethereum.crypto.hash.Hash32 (| + message_hash_bytes + |) in + let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + address, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..3743df8848 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/identity.v @@ -0,0 +1,36 @@ +(* +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 spurious_dragon.vm. +Require spurious_dragon.vm.gas. + +Definition identity : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..aef3392938 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.v @@ -0,0 +1,20 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require spurious_dragon.fork_types. +Require spurious_dragon.vm.precompiled_contracts.ecrecover. +Require spurious_dragon.vm.precompiled_contracts.identity. +Require spurious_dragon.vm.precompiled_contracts.ripemd160. +Require 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..bc5e73dd3c --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,42 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + let* hash_bytes := hashlib.["new"] (| + (* TODO expression *), + data + |).["digest"] (| + + |) in + let* padded_hash := left_pad_zero_bytes (| + hash_bytes, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..da6972d411 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.v @@ -0,0 +1,32 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..3641ac12f8 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/runtime.v @@ -0,0 +1,49 @@ +(* +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 spurious_dragon.vm.instructions. + +Definition get_valid_jump_destinations : M unit := + (* + 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. + *) + let* valid_jump_destinations := set (| + + |) in + let* pc := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..ad7f0e3e24 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/stack.v @@ -0,0 +1,53 @@ +(* +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 spurious_dragon.vm.exceptions. + +Definition pop : M unit := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + + +Definition push : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + 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..ef0fa3436d --- /dev/null +++ b/coq/ethereum/tangerine_whistle/__init__.v @@ -0,0 +1,8 @@ +(* +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..a5fd5f862a --- /dev/null +++ b/coq/ethereum/tangerine_whistle/blocks.v @@ -0,0 +1,19 @@ +(* +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 ..crypto.hash. +Require tangerine_whistle.fork_types. +Require 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..a0903ce0a8 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/bloom.v @@ -0,0 +1,66 @@ +(* +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 tangerine_whistle.blocks. +Require tangerine_whistle.fork_types. + +Definition add_to_bloom : 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. + *) + let* hash := ethereum.crypto.hash.keccak256 (| + bloom_entry + |) in + (* TODO statement *) + + +Definition logs_bloom : M unit := + (* + 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 *) + 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..6372706b12 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/fork.v @@ -0,0 +1,744 @@ +(* +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 tangerine_whistle.blocks. +Require tangerine_whistle.bloom. +Require tangerine_whistle.fork_types. +Require tangerine_whistle.state. +Require tangerine_whistle.transactions. +Require tangerine_whistle.trie. +Require tangerine_whistle.utils.message. +Require tangerine_whistle.vm.interpreter. + +Definition apply_fork : M unit := + (* + 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 *) + + +Definition get_last_256_block_hashes : M unit := + (* + 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. + *) + let* recent_blocks := (* TODO expression *) in + (* TODO statement *) + let* recent_block_hashes := (* TODO expression *) in + (* TODO statement *) + let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *).["header"] + |) + |) in + do* recent_block_hashes.["append"] (| + most_recent_block_hash + |) in + (* TODO statement *) + + +Definition state_transition : 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`. + *) + let* parent_header := (* TODO expression *).["header"] in + do* validate_header (| + block.["header"], + parent_header + |) in + do* validate_ommers (| + block.["ommers"], + block.["header"], + chain + |) in + let* apply_body_output := apply_body (| + chain.["state"], + get_last_256_block_hashes (| + chain + |), + block.["header"].["coinbase"], + block.["header"].["number"], + block.["header"].["gas_limit"], + block.["header"].["timestamp"], + block.["header"].["difficulty"], + block.["transactions"], + block.["ommers"] + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* chain.["blocks"].["append"] (| + block + |) in + (* TODO statement *) + + +Definition validate_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 *) + let* block_difficulty := calculate_block_difficulty (| + header.["number"], + header.["timestamp"], + parent_header.["timestamp"], + parent_header.["difficulty"] + |) in + (* TODO statement *) + let* block_parent_hash := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + parent_header + |) + |) in + (* TODO statement *) + do* validate_proof_of_work (| + header + |) in + + +Definition generate_header_hash_for_pow : M unit := + (* + 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. + *) + let* header_data_without_pow_artefacts := (* TODO expression *) in + (* TODO statement *) + + +Definition validate_proof_of_work : 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. + *) + let* header_hash := generate_header_hash_for_pow (| + header + |) in + let* cache := ethereum.ethash.generate_cache (| + header.["number"] + |) in + (* TODO assignment *) + (* TODO statement *) + let* limit := (* TODO expression *) in + (* TODO statement *) + + +Definition check_transaction : M unit := + (* + 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 *) + let* sender_address := recover_sender (| + tx + |) in + (* TODO statement *) + + +Definition make_receipt : M unit := + (* + 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. + *) + let* receipt := blocks.Receipt (| + + |) in + (* TODO statement *) + + +Definition apply_body : M unit := + (* + 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. + *) + let* gas_available := block_gas_limit in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* pay_rewards (| + state, + block_number, + coinbase, + ommers + |) in + let* block_gas_used := (* TODO expression *) in + let* block_logs_bloom := bloom.logs_bloom (| + block_logs + |) in + (* TODO statement *) + + +Definition validate_ommers : 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. + *) + let* block_hash := rlp.["rlp_hash"] (| + block_header + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* ommers_hashes := (* TODO expression *) in + (* TODO statement *) + let* recent_canonical_blocks := (* TODO expression *) in + let* recent_canonical_block_hashes := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition pay_rewards : 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. + *) + let* ommer_count := ethereum_types.numeric.U256 (| + len (| + ommers + |) + |) in + let* miner_reward := (* TODO expression *) in + do* state.create_ether (| + state, + coinbase, + miner_reward + |) in + (* TODO statement *) + + +Definition process_transaction : M unit := + (* + 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 *) + let* sender := env.["origin"] in + let* sender_account := state.get_account (| + env.["state"], + sender + |) in + let* gas_fee := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* gas := (* TODO expression *) in + do* state.increment_nonce (| + env.["state"], + sender + |) in + let* sender_balance_after_gas_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + ethereum_types.numeric.U256 (| + sender_balance_after_gas_fee + |) + |) in + let* message := utils.message.prepare_message (| + sender, + tx.["to"], + tx.["value"], + tx.["data"], + gas, + env + |) in + let* output := vm.interpreter.process_message_call (| + message, + env + |) in + let* gas_used := (* TODO expression *) in + let* gas_refund := min (| + (* TODO expression *), + ethereum_types.numeric.Uint (| + output.["refund_counter"] + |) + |) in + let* gas_refund_amount := (* TODO expression *) in + let* transaction_fee := (* TODO expression *) in + let* total_gas_used := (* TODO expression *) in + let* sender_balance_after_refund := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + sender, + sender_balance_after_refund + |) in + let* coinbase_balance_after_mining_fee := (* TODO expression *) in + do* state.set_account_balance (| + env.["state"], + env.["coinbase"], + coinbase_balance_after_mining_fee + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition validate_transaction : M unit := + (* + 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 *) + + +Definition calculate_intrinsic_cost : M unit := + (* + 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. + *) + let* data_cost := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition recover_sender : M unit := + (* + 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 *) + let* public_key := ethereum.crypto.elliptic_curve.secp256k1_recover (| + r, + s, + (* TODO expression *), + signing_hash (| + tx + |) + |) in + (* TODO statement *) + + +Definition signing_hash : M unit := + (* + 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 *) + + +Definition compute_header_hash : M unit := + (* + 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 *) + + +Definition check_gas_limit : M unit := + (* + 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. + *) + let* max_adjustment_delta := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_block_difficulty : M unit := + (* + 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. + *) + let* offset := (* TODO expression *) in + let* difficulty := (* TODO expression *) in + let* num_bomb_periods := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..14de99d5e5 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/fork_types.v @@ -0,0 +1,29 @@ +(* +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 ..crypto.hash. + +Definition encode_account : M unit := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + 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..ab82e8b22f --- /dev/null +++ b/coq/ethereum/tangerine_whistle/state.v @@ -0,0 +1,471 @@ +(* +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 tangerine_whistle.fork_types. +Require tangerine_whistle.trie. + +Definition close_state : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition begin_transaction : 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* state.["_snapshots"].["append"] (| + (* TODO expression *) + |) in + + +Definition commit_transaction : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* state.["_snapshots"].["pop"] (| + + |) in + + +Definition rollback_transaction : 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 *) + + +Definition get_account : M unit := + (* + 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. + *) + let* account := get_account_optional (| + state, + address + |) in + (* TODO statement *) + + +Definition get_account_optional : M unit := + (* + 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. + *) + let* account := trie.trie_get (| + state.["_main_trie"], + address + |) in + (* TODO statement *) + + +Definition set_account : 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 (| + state.["_main_trie"], + address, + account + |) in + + +Definition destroy_account : 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* destroy_storage (| + state, + address + |) in + do* set_account (| + state, + address, + (* TODO expression *) + |) in + + +Definition destroy_storage : 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 *) + + +Definition get_storage : M unit := + (* + 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. + *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + let* value := trie.trie_get (| + trie, + key + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition set_storage : 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 *) + let* trie := state.["_storage_tries"].["get"] (| + address + |) in + (* TODO statement *) + do* trie.trie_set (| + trie, + key, + value + |) in + (* TODO statement *) + + +Definition storage_root : M unit := + (* + 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 *) + + +Definition state_root : M unit := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition account_exists : M unit := + (* + 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 *) + + +Definition account_has_code_or_nonce : M unit := + (* + 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. + *) + let* account := get_account (| + state, + address + |) in + (* TODO statement *) + + +Definition modify_state : M unit := + (* + Modify an `Account` in the `State`. + *) + do* set_account (| + state, + address, + ethereum_types.frozen.modify (| + get_account (| + state, + address + |), + f + |) + |) in + + +Definition move_ether : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* modify_state (| + state, + sender_address, + reduce_sender_balance + |) in + do* modify_state (| + state, + recipient_address, + increase_recipient_balance + |) in + + +Definition set_account_balance : 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* modify_state (| + state, + address, + set_balance + |) in + + +Definition touch_account : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + + +Definition increment_nonce : 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* modify_state (| + state, + address, + increase_nonce + |) in + + +Definition set_code : 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* modify_state (| + state, + address, + write_code + |) in + + +Definition create_ether : 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* modify_state (| + state, + address, + increase_balance + |) in + 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..4458fc223d --- /dev/null +++ b/coq/ethereum/tangerine_whistle/transactions.v @@ -0,0 +1,12 @@ +(* +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 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..5f0ab29642 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/trie.v @@ -0,0 +1,274 @@ +(* +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 : M unit := + (* + 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 *) + let* encoded := rlp.["encode"] (| + unencoded + |) in + (* TODO statement *) + + +Definition encode_node : M unit := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + + +Definition copy_trie : M unit := + (* + 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 *) + + +Definition trie_set : 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 *) + + +Definition trie_get : M unit := + (* + 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 *) + + +Definition common_prefix_length : M unit := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + + +Definition nibble_list_to_compact : M unit := + (* + 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. + *) + let* compact := bytearray (| + + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition bytes_to_nibble_list : M unit := + (* + 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. + *) + let* nibble_list := bytearray (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition _prepare_trie : M unit := + (* + 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 *) + + +Definition root : M unit := + (* + 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. + *) + let* obj := _prepare_trie (| + trie, + get_storage_root + |) in + let* root_node := encode_internal_node (| + patricialize (| + obj, + Uint (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + + +Definition patricialize : M unit := + (* + 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 *) + let* arbitrary_key := next (| + iter (| + obj + |) + |) in + (* TODO statement *) + let* substring := (* TODO expression *) in + let* prefix_length := len (| + substring + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* value := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..beff4482b1 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/utils/__init__.v @@ -0,0 +1,4 @@ +(* +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..e20ee01fa7 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/utils/address.v @@ -0,0 +1,67 @@ +(* +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 tangerine_whistle.fork_types. + +Definition to_address : M unit := + (* + 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 *) + + +Definition compute_contract_address : M unit := + (* + 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. + *) + let* computed_address := ethereum.crypto.hash.keccak256 (| + rlp.["encode"] (| + (* TODO expression *) + |) + |) in + let* canonical_address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + canonical_address, + (* TODO expression *) + |) in + (* TODO statement *) + 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..b3ef61f1c6 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/utils/hexadecimal.v @@ -0,0 +1,68 @@ +(* +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 tangerine_whistle.fork_types. + +Definition hex_to_root : M unit := + (* + 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 *) + + +Definition hex_to_bloom : M unit := + (* + 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 *) + + +Definition hex_to_address : M unit := + (* + 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 *) + 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..c0aeaa4554 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/utils/message.v @@ -0,0 +1,56 @@ +(* +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 tangerine_whistle.fork_types. +Require tangerine_whistle.state. +Require tangerine_whistle.vm. +Require tangerine_whistle.utils.address. + +Definition prepare_message : M unit := + (* + 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 *) + 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..d53025e199 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/__init__.v @@ -0,0 +1,56 @@ +(* +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 tangerine_whistle.blocks. +Require tangerine_whistle.fork_types. +Require tangerine_whistle.state. + +Definition incorporate_child_on_success : 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* evm.["accounts_to_delete"].["update"] (| + child_evm.["accounts_to_delete"] + |) in + + +Definition incorporate_child_on_error : 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 *) + 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..1784494410 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/exceptions.v @@ -0,0 +1,15 @@ +(* +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..5b97f89352 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/gas.v @@ -0,0 +1,151 @@ +(* +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 tangerine_whistle.vm.exceptions. + +Definition charge_gas : 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 (| + int (| + amount + |) + |) + |) in + (* TODO statement *) + + +Definition calculate_memory_gas_cost : M unit := + (* + 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. + *) + let* size_in_words := (* TODO expression *) in + let* linear_cost := (* TODO expression *) in + let* quadratic_cost := (* TODO expression *) in + let* total_gas_cost := (* TODO expression *) in + (* TODO statement *) + + +Definition calculate_gas_extend_memory : M unit := + (* + 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` + *) + let* size_to_extend := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* to_be_paid := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* current_size := ethereum_types.numeric.Uint (| + len (| + memory + |) + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition calculate_message_call_gas : M unit := + (* + 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` + *) + let* call_stipend := (* TODO expression *) in + (* TODO statement *) + let* gas := min (| + gas, + max_message_call_gas (| + (* TODO expression *) + |) + |) in + (* TODO statement *) + + +Definition max_message_call_gas : M unit := + (* + 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 *) + 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..b36b1ebfef --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/__init__.v @@ -0,0 +1,15 @@ +(* +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..fae846724f --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/arithmetic.v @@ -0,0 +1,387 @@ +(* +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 tangerine_whistle.vm.gas. +Require tangerine_whistle.vm.stack. + +Definition add : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_add"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition sub : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := x.["wrapping_sub"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mul : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + let* result := x.["wrapping_mul"] (| + y + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition div : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |) in + let* divisor := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + quotient + |) in + (* TODO statement *) + + +Definition sdiv : 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. + + *) + let* dividend := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* divisor := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + quotient + |) + |) in + (* TODO statement *) + + +Definition mod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + remainder + |) in + (* TODO statement *) + + +Definition smod : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* y := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_signed"] (| + remainder + |) + |) in + (* TODO statement *) + + +Definition addmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition mulmod : 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. + + *) + let* x := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* y := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* z := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_MID + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition exp : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* base := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* exponent_bits := exponent.["bit_length"] (| + + |) in + let* exponent_bytes := (* TODO expression *) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* result := ethereum_types.numeric.U256 (| + pow (| + base, + exponent, + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signextend : 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. + + *) + let* byte_num := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..b68bd75bbe --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/bitwise.v @@ -0,0 +1,156 @@ +(* +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 tangerine_whistle.vm.gas. +Require tangerine_whistle.vm.stack. + +Definition bitwise_and : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_or : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_xor : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + let* y := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition bitwise_not : 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. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + do* stack.push (| + evm.["stack"], + (* TODO expression *) + |) in + (* TODO statement *) + + +Definition get_byte : 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. + + *) + let* byte_index := stack.pop (| + evm.["stack"] + |) in + let* word := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..0d927d3693 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/block.v @@ -0,0 +1,183 @@ +(* +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 tangerine_whistle.vm.gas. +Require tangerine_whistle.vm.stack. + +Definition block_hash : 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. + + *) + let* block_number := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BLOCK_HASH + |) in + let* max_block_number := (* TODO expression *) in + (* TODO statement *) + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + + +Definition coinbase : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["coinbase"] + |) + |) in + (* TODO statement *) + + +Definition timestamp : 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 (| + evm.["stack"], + evm.["env"].["time"] + |) in + (* TODO statement *) + + +Definition number : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["number"] + |) + |) in + (* TODO statement *) + + +Definition difficulty : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["difficulty"] + |) + |) in + (* TODO statement *) + + +Definition gas_limit : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_limit"] + |) + |) in + (* TODO statement *) + 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..d813938264 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/comparison.v @@ -0,0 +1,206 @@ +(* +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 tangerine_whistle.vm.gas. +Require tangerine_whistle.vm.stack. + +Definition less_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_less_than : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition greater_than : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition signed_greater_than : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* left := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + let* right := stack.pop (| + evm.["stack"] + |).["to_signed"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition equal : 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. + + *) + let* left := stack.pop (| + evm.["stack"] + |) in + let* right := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + + +Definition is_zero : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* x := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* result := ethereum_types.numeric.U256 (| + (* TODO expression *) + |) in + do* stack.push (| + evm.["stack"], + result + |) in + (* TODO statement *) + 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..2187e73a8c --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/control_flow.v @@ -0,0 +1,156 @@ +(* +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 tangerine_whistle.vm.gas. +Require tangerine_whistle.vm.exceptions. +Require tangerine_whistle.vm.stack. + +Definition stop : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + + +Definition jump : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_MID + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition jumpi : 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. + + *) + let* jump_dest := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* conditional_value := stack.pop (| + evm.["stack"] + |) in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_HIGH + |) in + (* TODO statement *) + (* TODO assignment *) + + +Definition pc : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["pc"] + |) + |) in + (* TODO statement *) + + +Definition gas_left : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + + +Definition jumpdest : 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 *) + (* TODO statement *) + 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..382a382b7b --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/environment.v @@ -0,0 +1,434 @@ +(* +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 tangerine_whistle.state. +Require tangerine_whistle.utils.address. +Require tangerine_whistle.vm.memory. +Require tangerine_whistle.vm.gas. +Require tangerine_whistle.vm.stack. + +Definition address : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["current_target"] + |) + |) in + (* TODO statement *) + + +Definition balance : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BALANCE + |) in + let* balance := state.get_account (| + evm.["env"].["state"], + address + |).["balance"] in + do* stack.push (| + evm.["stack"], + balance + |) in + (* TODO statement *) + + +Definition origin : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["env"].["origin"] + |) + |) in + (* TODO statement *) + + +Definition caller : 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 (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + evm.["message"].["caller"] + |) + |) in + (* TODO statement *) + + +Definition callvalue : 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 (| + evm.["stack"], + evm.["message"].["value"] + |) in + (* TODO statement *) + + +Definition calldataload : 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. + + *) + let* start_index := stack.pop (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_VERY_LOW + |) in + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + start_index, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + value + |) + |) in + (* TODO statement *) + + +Definition calldatasize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["message"].["data"] + |) + |) + |) in + (* TODO statement *) + + +Definition calldatacopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* data_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["message"].["data"], + data_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition codesize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["code"] + |) + |) + |) in + (* TODO statement *) + + +Definition codecopy : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := vm.memory.buffer_read (| + evm.["code"], + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + + +Definition gasprice : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + evm.["env"].["gas_price"] + |) + |) in + (* TODO statement *) + + +Definition extcodesize : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + do* gas.charge_gas (| + evm, + gas.GAS_EXTERNAL + |) in + let* codesize := ethereum_types.numeric.U256 (| + len (| + state.get_account (| + evm.["env"].["state"], + address + |).["code"] + |) + |) in + do* stack.push (| + evm.["stack"], + codesize + |) in + (* TODO statement *) + + +Definition extcodecopy : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* code_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* copy_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* code := state.get_account (| + evm.["env"].["state"], + address + |).["code"] in + let* value := vm.memory.buffer_read (| + code, + code_start_index, + size + |) in + do* vm.memory.memory_write (| + evm.["memory"], + memory_start_index, + value + |) in + (* TODO statement *) + 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..7e9a06cdea --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/keccak.v @@ -0,0 +1,67 @@ +(* +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 tangerine_whistle.vm.gas. +Require tangerine_whistle.vm.memory. +Require tangerine_whistle.vm.stack. + +Definition keccak : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* words := (* TODO expression *) in + let* word_gas_cost := (* TODO expression *) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* data := memory.memory_read_bytes (| + evm.["memory"], + memory_start_index, + size + |) in + let* hash := ethereum.crypto.hash.keccak256 (| + data + |) in + do* stack.push (| + evm.["stack"], + ethereum_types.numeric.U256.["from_be_bytes"] (| + hash + |) + |) in + (* TODO statement *) + 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..358dc7cedf --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/log.v @@ -0,0 +1,59 @@ +(* +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 tangerine_whistle.blocks. +Require tangerine_whistle.vm.gas. +Require tangerine_whistle.vm.memory. +Require tangerine_whistle.vm.stack. + +Definition log_n : 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. + + *) + let* memory_start_index := stack.pop (| + evm.["stack"] + |) in + let* size := stack.pop (| + evm.["stack"] + |) in + let* topics := (* TODO expression *) in + (* TODO statement *) + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* log_entry := blocks.Log (| + + |) in + (* TODO assignment *) + (* TODO statement *) + 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..5b7c96f8f5 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/memory.v @@ -0,0 +1,158 @@ +(* +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 tangerine_whistle.vm.gas. +Require tangerine_whistle.vm.memory. +Require tangerine_whistle.vm.stack. + +Definition mstore : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* memory.memory_write (| + evm.["memory"], + start_position, + value + |) in + (* TODO statement *) + + +Definition mstore8 : 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. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + (* TODO expression *) + |) in + do* memory.memory_write (| + evm.["memory"], + start_position, + normalized_bytes_value + |) in + (* TODO statement *) + + +Definition mload : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* start_position := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.memory_read_bytes (| + evm.["memory"], + start_position, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition msize : 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 (| + evm.["stack"], + ethereum_types.numeric.U256 (| + len (| + evm.["memory"] + |) + |) + |) in + (* TODO statement *) + 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..d8caa6a1e1 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/stack.v @@ -0,0 +1,133 @@ +(* +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 tangerine_whistle.vm.exceptions. +Require tangerine_whistle.vm.gas. +Require tangerine_whistle.vm.memory. + +Definition pop : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* stack.["pop"] (| + evm.["stack"] + |) in + do* gas.charge_gas (| + evm, + gas.GAS_BASE + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition push_n : 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 + let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| + memory.buffer_read (| + evm.["code"], + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + num_bytes + |) + |) + |) in + do* stack.["push"] (| + evm.["stack"], + data_to_push + |) in + (* TODO statement *) + + +Definition dup_n : 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 *) + let* data_to_duplicate := (* TODO expression *) in + do* stack.["push"] (| + evm.["stack"], + data_to_duplicate + |) in + (* TODO statement *) + + +Definition swap_n : 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 *) + (* TODO statement *) + 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..578f5bb6ae --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/storage.v @@ -0,0 +1,88 @@ +(* +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 tangerine_whistle.state. +Require tangerine_whistle.vm.gas. +Require tangerine_whistle.vm.stack. + +Definition sload : 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. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + do* gas.charge_gas (| + evm, + gas.GAS_SLOAD + |) in + let* value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + do* stack.push (| + evm.["stack"], + value + |) in + (* TODO statement *) + + +Definition sstore : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + let* key := stack.pop (| + evm.["stack"] + |).["to_be_bytes32"] (| + + |) in + let* new_value := stack.pop (| + evm.["stack"] + |) in + let* current_value := state.get_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key + |) in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + do* state.set_storage (| + evm.["env"].["state"], + evm.["message"].["current_target"], + key, + new_value + |) in + (* TODO statement *) + 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..fdf3bbe166 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/system.v @@ -0,0 +1,386 @@ +(* +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 tangerine_whistle.fork_types. +Require tangerine_whistle.state. +Require tangerine_whistle.utils.address. +Require tangerine_whistle.vm.gas. +Require tangerine_whistle.vm.memory. +Require tangerine_whistle.vm.stack. + +Definition create : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + let* endowment := stack.pop (| + evm.["stack"] + |) in + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + let* create_message_gas := gas.max_message_call_gas (| + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |) + |) in + (* TODO statement *) + (* TODO statement *) + let* sender_address := evm.["message"].["current_target"] in + let* sender := state.get_account (| + evm.["env"].["state"], + sender_address + |) in + let* contract_address := utils.address.compute_contract_address (| + evm.["message"].["current_target"], + state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["nonce"] + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition return_ : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* memory_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + + +Definition generic_call : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO statement *) + let* call_data := memory.memory_read_bytes (| + evm.["memory"], + memory_input_start_position, + memory_input_size + |) in + let* code := state.get_account (| + evm.["env"].["state"], + code_address + |).["code"] in + let* child_message := Message (| + + |) in + let* child_evm := process_message (| + child_message, + evm.["env"] + |) in + (* TODO statement *) + let* actual_output_size := min (| + memory_output_size, + ethereum_types.numeric.U256 (| + len (| + child_evm.["output"] + |) + |) + |) in + do* memory.memory_write (| + evm.["memory"], + memory_output_start_position, + (* TODO expression *) + |) in + + +Definition call : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* to := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* _account_exists := state.account_exists (| + evm.["env"].["state"], + to + |) in + let* create_gas_cost := (* TODO expression *) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition callcode : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* value := stack.pop (| + evm.["stack"] + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* to := evm.["message"].["current_target"] in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* transfer_gas_cost := (* TODO expression *) in + let* message_call_gas := gas.calculate_message_call_gas (| + value, + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + (* TODO expression *) + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + let* sender_balance := state.get_account (| + evm.["env"].["state"], + evm.["message"].["current_target"] + |).["balance"] in + (* TODO statement *) + (* TODO statement *) + + +Definition selfdestruct : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* beneficiary := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* gas_cost := gas.GAS_SELF_DESTRUCT in + (* TODO statement *) + let* originator := evm.["message"].["current_target"] in + let* refunded_accounts := evm.["accounts_to_delete"] in + let* parent_evm := evm.["message"].["parent_evm"] in + (* TODO statement *) + (* TODO statement *) + do* gas.charge_gas (| + evm, + gas_cost + |) in + let* beneficiary_balance := state.get_account (| + evm.["env"].["state"], + beneficiary + |).["balance"] in + let* originator_balance := state.get_account (| + evm.["env"].["state"], + originator + |).["balance"] in + do* state.set_account_balance (| + evm.["env"].["state"], + beneficiary, + (* TODO expression *) + |) in + do* state.set_account_balance (| + evm.["env"].["state"], + originator, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + do* evm.["accounts_to_delete"].["add"] (| + originator + |) in + (* TODO assignment *) + (* TODO statement *) + + +Definition delegatecall : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* gas := ethereum_types.numeric.Uint (| + stack.pop (| + evm.["stack"] + |) + |) in + let* code_address := utils.address.to_address (| + stack.pop (| + evm.["stack"] + |) + |) in + let* memory_input_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_input_size := stack.pop (| + evm.["stack"] + |) in + let* memory_output_start_position := stack.pop (| + evm.["stack"] + |) in + let* memory_output_size := stack.pop (| + evm.["stack"] + |) in + let* extend_memory := gas.calculate_gas_extend_memory (| + evm.["memory"], + (* TODO expression *) + |) in + let* message_call_gas := gas.calculate_message_call_gas (| + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + gas, + ethereum_types.numeric.Uint (| + evm.["gas_left"] + |), + extend_memory.["cost"], + gas.GAS_CALL + |) in + do* gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO statement *) + do* generic_call (| + evm, + message_call_gas.["stipend"], + evm.["message"].["value"], + evm.["message"].["caller"], + evm.["message"].["current_target"], + code_address, + (* TODO expression *), + memory_input_start_position, + memory_input_size, + memory_output_start_position, + memory_output_size + |) in + (* TODO statement *) + 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..f8d35c19b1 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/interpreter.v @@ -0,0 +1,151 @@ +(* +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 tangerine_whistle.blocks. +Require tangerine_whistle.fork_types. +Require tangerine_whistle.state. +Require tangerine_whistle.vm. +Require tangerine_whistle.vm.gas. +Require tangerine_whistle.vm.precompiled_contracts.mapping. +Require tangerine_whistle.vm.exceptions. +Require tangerine_whistle.vm.instructions. +Require tangerine_whistle.vm.runtime. + +Definition process_message_call : M unit := + (* + 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 *) + let* tx_end := ethereum.trace.TransactionEnd (| + (* TODO expression *), + evm.["output"], + evm.["error"] + |) in + do* ethereum.trace.evm_trace (| + evm, + tx_end + |) in + (* TODO statement *) + + +Definition process_create_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.destroy_storage (| + env.["state"], + message.["current_target"] + |) in + let* evm := process_message (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition process_message : M unit := + (* + 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 (| + env.["state"] + |) in + do* state.touch_account (| + env.["state"], + message.["current_target"] + |) in + (* TODO statement *) + let* evm := execute_code (| + message, + env + |) in + (* TODO statement *) + (* TODO statement *) + + +Definition execute_code : M unit := + (* + 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 + *) + let* code := message.["code"] in + let* valid_jump_destinations := runtime.get_valid_jump_destinations (| + code + |) in + let* evm := Evm (| + + |) in + (* TODO statement *) + (* TODO statement *) + 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..94b6a44639 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/memory.v @@ -0,0 +1,75 @@ +(* +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 : 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 *) + + +Definition memory_read_bytes : M unit := + (* + 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 *) + + +Definition buffer_read : M unit := + (* + 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 *) + 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..41f2c4b229 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.v @@ -0,0 +1,16 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require 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..b10d7b92f0 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,93 @@ +(* +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 tangerine_whistle.vm. +Require tangerine_whistle.vm.gas. +Require tangerine_whistle.vm.memory. + +Definition ecrecover : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + do* vm.gas.charge_gas (| + evm, + vm.gas.GAS_ECRECOVER + |) in + let* message_hash_bytes := vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) in + let* message_hash := ethereum.crypto.hash.Hash32 (| + message_hash_bytes + |) in + let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| + vm.memory.buffer_read (| + data, + ethereum_types.numeric.U256 (| + (* TODO expression *) + |), + ethereum_types.numeric.U256 (| + (* TODO expression *) + |) + |) + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + let* address := (* TODO expression *) in + let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| + address, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..740ea286f6 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.v @@ -0,0 +1,36 @@ +(* +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 tangerine_whistle.vm. +Require tangerine_whistle.vm.gas. + +Definition identity : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* vm.gas.charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..f129cdd4e4 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.v @@ -0,0 +1,20 @@ +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require tangerine_whistle.fork_types. +Require tangerine_whistle.vm.precompiled_contracts.ecrecover. +Require tangerine_whistle.vm.precompiled_contracts.identity. +Require tangerine_whistle.vm.precompiled_contracts.ripemd160. +Require 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..bc5e73dd3c --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,42 @@ +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + let* hash_bytes := hashlib.["new"] (| + (* TODO expression *), + data + |).["digest"] (| + + |) in + let* padded_hash := left_pad_zero_bytes (| + hash_bytes, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..da6972d411 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.v @@ -0,0 +1,32 @@ +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + let* data := evm.["message"].["data"] in + let* word_count := (* TODO expression *) in + do* charge_gas (| + evm, + (* TODO expression *) + |) in + (* TODO assignment *) + 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..7876a3db70 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/runtime.v @@ -0,0 +1,49 @@ +(* +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 tangerine_whistle.vm.instructions. + +Definition get_valid_jump_destinations : M unit := + (* + 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. + *) + let* valid_jump_destinations := set (| + + |) in + let* pc := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + (* TODO statement *) + 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..04f01207b7 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/stack.v @@ -0,0 +1,53 @@ +(* +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 tangerine_whistle.vm.exceptions. + +Definition pop : M unit := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + + +Definition push : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + 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..cfb74ecc24 --- /dev/null +++ b/coq/ethereum/trace.v @@ -0,0 +1,26 @@ +(* +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 : M unit := + (* + An [`EvmTracer`] that discards all events. + + [`EvmTracer`]: ref:ethereum.trace.EvmTracer + *) + 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..782ba6d087 --- /dev/null +++ b/coq/ethereum/utils/__init__.v @@ -0,0 +1,14 @@ +(* +Utility functions used in this specification. +*) + +Require dataclasses. +Require typing. + +Definition has_field : M unit := + (* + Returns `True` if `class_` has a field with the given `name`. + *) + (* TODO statement *) + (* TODO statement *) + 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..436e401845 --- /dev/null +++ b/coq/ethereum/utils/byte.v @@ -0,0 +1,55 @@ +(* +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 : M unit := + (* + 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 *) + + +Definition right_pad_zero_bytes : M unit := + (* + 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 *) + 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..23bfddfc14 --- /dev/null +++ b/coq/ethereum/utils/hexadecimal.v @@ -0,0 +1,206 @@ +(* +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 : M unit := + (* + 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 *) + + +Definition remove_hex_prefix : M unit := + (* + 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 *) + + +Definition hex_to_bytes : M unit := + (* + 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 *) + + +Definition hex_to_bytes8 : M unit := + (* + 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 *) + + +Definition hex_to_bytes20 : M unit := + (* + 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 *) + + +Definition hex_to_bytes32 : M unit := + (* + 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 *) + + +Definition hex_to_bytes256 : M unit := + (* + 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 *) + + +Definition hex_to_hash : M unit := + (* + 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 *) + + +Definition hex_to_uint : M unit := + (* + 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 *) + + +Definition hex_to_u64 : M unit := + (* + 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 *) + + +Definition hex_to_u256 : M unit := + (* + 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 *) + 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..5e2ab66ba7 --- /dev/null +++ b/coq/ethereum/utils/numeric.v @@ -0,0 +1,186 @@ +(* +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 : M unit := + (* + 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 *) + + +Definition ceil32 : M unit := + (* + 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`. + *) + let* ceiling := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* remainder := (* TODO expression *) in + (* TODO statement *) + + +Definition is_prime : M unit := + (* + 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. + *) + let* number := int (| + number + |) in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + + +Definition le_bytes_to_uint32_sequence : M unit := + (* + 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. + *) + let* sequence := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + + +Definition le_uint32_sequence_to_bytes : M unit := + (* + 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. + *) + let* result_bytes := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + + +Definition le_uint32_sequence_to_uint : M unit := + (* + 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. + *) + let* sequence_as_bytes := le_uint32_sequence_to_bytes (| + sequence + |) in + (* TODO statement *) + + +Definition taylor_exponential : M unit := + (* + 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). + + *) + let* i := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* output := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + let* numerator_accumulated := (* TODO expression *) in + (* TODO statement *) + (* TODO statement *) + 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..12986a00d1 --- /dev/null +++ b/coq/ethereum/utils/safe_arithmetic.v @@ -0,0 +1,77 @@ +(* +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 unit := + (* + 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 *) + + +Definition u256_safe_multiply : M unit := + (* + 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. + *) + let* result := ethereum_types.numeric.Uint (| + (* TODO expression *) + |) in + (* TODO statement *) + diff --git a/coq/translate.py b/coq/translate.py index 585b81a789..ba259bfac5 100644 --- a/coq/translate.py +++ b/coq/translate.py @@ -3,30 +3,110 @@ """ import ast from pathlib import Path +from typing import Literal -# For now, we only translate the Cancun version -source_root_dir = Path("../src/ethereum/cancun") +source_root_dir = Path("../src/ethereum") -def to_coq(tree: ast.AST) -> str: - if isinstance(tree, ast.Module): - output = "" +def indent(text: str) -> str: + levels = 2 + return "\n".join( + ( + " " * levels + line + if line.strip() != "" + else line + ) + for line in text.splitlines() + ) + + +def to_coq_expression(import_aliases: dict[str, str], node: ast.expr) -> str: + if isinstance(node, ast.Name): + if node.id in import_aliases: + return import_aliases[node.id] + "." + node.id + return node.id + if isinstance(node, ast.Call): + return \ + to_coq_expression(import_aliases, node.func) + " (|\n" + \ + indent( + ',\n'.join(to_coq_expression(import_aliases, arg) for arg in node.args) + ) + "\n" + \ + "|)" + if isinstance(node, ast.Attribute): + return \ + to_coq_expression(import_aliases, node.value) + ".[\"" + node.attr + "\"]" + return "(* TODO expression *)" + + +def to_coq_statement(import_aliases: dict[str, str], 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(import_aliases, 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 \ + "let* " + node.targets[0].id + " := " + \ + to_coq_expression(import_aliases, node.value) + " in" + return "(* TODO assignment *)" + return "(* TODO statement *)" + + +def to_coq_function_def(import_aliases: dict[str, str], node: ast.FunctionDef) -> str: + output = f"Definition {node.name} : M unit :=\n" + + for statement in node.body: + output += indent(to_coq_statement(import_aliases, statement)) + "\n" - if len(tree.body) >= 1 and \ - isinstance(tree.body[0], ast.Expr) and \ - isinstance(tree.body[0].value, ast.Constant): - output += f"(*{tree.body[0].value.value}*)\n\n" - else: - return "No description available at the beginning of the file" + 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 = "" + mode: ToCoqMode = 'header_comment' import_aliases: dict[str, str] = {} - for node in tree.body[1:]: - if isinstance(node, ast.ImportFrom): - if node.module is not None: - for alias in node.names: - import_aliases[alias.name] = node.module - output += f"Require {node.module}.\n" + + 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): + if node.module is not None: + for alias in node.names: + import_aliases[alias.name] = node.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}{node.module}.\n" + else: + mode = 'definitions' + if isinstance(node, ast.FunctionDef): + output += '\n' + output += to_coq_function_def(import_aliases, node) + "\n" return output @@ -41,7 +121,7 @@ def translate_file(file_path: Path) -> None: with open(file_path) as f: source = f.read() tree = ast.parse(source) - output_file_path = Path("translation") / file_path.relative_to(source_root_dir) + output_file_path = Path("ethereum") / 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) @@ -52,7 +132,7 @@ def translate_file(file_path: Path) -> None: # Output the Coq file with open(output_file_path.with_suffix(".v"), "w") as f: - f.write(to_coq(tree)) + f.write(to_coq(file_path.parent, tree)) # We iterate over all the files in the source directory, recursively diff --git a/coq/translation/bloom.v b/coq/translation/bloom.v deleted file mode 100644 index 1e3fd0cf86..0000000000 --- a/coq/translation/bloom.v +++ /dev/null @@ -1,23 +0,0 @@ -(* -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 blocks. -Require fork_types. diff --git a/coq/translation/fork.v b/coq/translation/fork.v deleted file mode 100644 index ae0cd5f2cd..0000000000 --- a/coq/translation/fork.v +++ /dev/null @@ -1,32 +0,0 @@ -(* -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 blocks. -Require bloom. -Require fork_types. -Require state. -Require transactions. -Require trie. -Require utils.hexadecimal. -Require utils.message. -Require vm. -Require vm.gas. -Require vm.interpreter. diff --git a/coq/translation/state.v b/coq/translation/state.v deleted file mode 100644 index f728b5afab..0000000000 --- a/coq/translation/state.v +++ /dev/null @@ -1,27 +0,0 @@ -(* -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 blocks. -Require fork_types. -Require trie. diff --git a/coq/translation/trie.v b/coq/translation/trie.v deleted file mode 100644 index c2223b9ad3..0000000000 --- a/coq/translation/trie.v +++ /dev/null @@ -1,26 +0,0 @@ -(* -State Trie -^^^^^^^^^^ - -.. contents:: Table of Contents - :backlinks: none - :local: - -Introduction ------------- - -The state trie is the structure responsible for storing -`.fork_types.Account` objects. -*) - -Require dataclasses. -Require typing. -Require ethereum_types.bytes. -Require ethereum_types.frozen. -Require ethereum_types.numeric. -Require ethereum.crypto.hash. -Require ethereum.shanghai. -Require ethereum.utils.hexadecimal. -Require blocks. -Require fork_types. -Require transactions. diff --git a/coq/translation/utils/address.v b/coq/translation/utils/address.v deleted file mode 100644 index 981ef4b450..0000000000 --- a/coq/translation/utils/address.v +++ /dev/null @@ -1,21 +0,0 @@ -(* -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 fork_types. diff --git a/coq/translation/utils/hexadecimal.v b/coq/translation/utils/hexadecimal.v deleted file mode 100644 index 6cc4882945..0000000000 --- a/coq/translation/utils/hexadecimal.v +++ /dev/null @@ -1,17 +0,0 @@ -(* -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 fork_types. diff --git a/coq/translation/utils/message.v b/coq/translation/utils/message.v deleted file mode 100644 index 0b1cdb7cd8..0000000000 --- a/coq/translation/utils/message.v +++ /dev/null @@ -1,23 +0,0 @@ -(* -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 fork_types. -Require state. -Require vm. -Require vm.precompiled_contracts.mapping. -Require address. diff --git a/coq/translation/vm/__init__.v b/coq/translation/vm/__init__.v deleted file mode 100644 index 9487aa222b..0000000000 --- a/coq/translation/vm/__init__.v +++ /dev/null @@ -1,24 +0,0 @@ -(* -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 blocks. -Require fork_types. -Require state. -Require precompiled_contracts. diff --git a/coq/translation/vm/gas.v b/coq/translation/vm/gas.v deleted file mode 100644 index 2f8165fe9f..0000000000 --- a/coq/translation/vm/gas.v +++ /dev/null @@ -1,22 +0,0 @@ -(* -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 blocks. -Require transactions. -Require exceptions. diff --git a/coq/translation/vm/instructions/arithmetic.v b/coq/translation/vm/instructions/arithmetic.v deleted file mode 100644 index a4d756f9b4..0000000000 --- a/coq/translation/vm/instructions/arithmetic.v +++ /dev/null @@ -1,18 +0,0 @@ -(* -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 gas. -Require stack. diff --git a/coq/translation/vm/instructions/bitwise.v b/coq/translation/vm/instructions/bitwise.v deleted file mode 100644 index ea6e70dd9e..0000000000 --- a/coq/translation/vm/instructions/bitwise.v +++ /dev/null @@ -1,17 +0,0 @@ -(* -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 gas. -Require stack. diff --git a/coq/translation/vm/instructions/block.v b/coq/translation/vm/instructions/block.v deleted file mode 100644 index e247e24b18..0000000000 --- a/coq/translation/vm/instructions/block.v +++ /dev/null @@ -1,17 +0,0 @@ -(* -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 gas. -Require stack. diff --git a/coq/translation/vm/instructions/comparison.v b/coq/translation/vm/instructions/comparison.v deleted file mode 100644 index 2bd22cc9f3..0000000000 --- a/coq/translation/vm/instructions/comparison.v +++ /dev/null @@ -1,17 +0,0 @@ -(* -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 gas. -Require stack. diff --git a/coq/translation/vm/instructions/control_flow.v b/coq/translation/vm/instructions/control_flow.v deleted file mode 100644 index 94774f38be..0000000000 --- a/coq/translation/vm/instructions/control_flow.v +++ /dev/null @@ -1,18 +0,0 @@ -(* -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 vm.gas. -Require exceptions. -Require stack. diff --git a/coq/translation/vm/instructions/environment.v b/coq/translation/vm/instructions/environment.v deleted file mode 100644 index 6afbd5a29c..0000000000 --- a/coq/translation/vm/instructions/environment.v +++ /dev/null @@ -1,25 +0,0 @@ -(* -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 fork_types. -Require state. -Require utils.address. -Require vm.memory. -Require exceptions. -Require gas. -Require stack. diff --git a/coq/translation/vm/instructions/keccak.v b/coq/translation/vm/instructions/keccak.v deleted file mode 100644 index 31fe83edc4..0000000000 --- a/coq/translation/vm/instructions/keccak.v +++ /dev/null @@ -1,20 +0,0 @@ -(* -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 gas. -Require memory. -Require stack. diff --git a/coq/translation/vm/instructions/log.v b/coq/translation/vm/instructions/log.v deleted file mode 100644 index f9f59c7815..0000000000 --- a/coq/translation/vm/instructions/log.v +++ /dev/null @@ -1,21 +0,0 @@ -(* -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 blocks. -Require exceptions. -Require gas. -Require memory. -Require stack. diff --git a/coq/translation/vm/instructions/memory.v b/coq/translation/vm/instructions/memory.v deleted file mode 100644 index 7cc1083cbe..0000000000 --- a/coq/translation/vm/instructions/memory.v +++ /dev/null @@ -1,20 +0,0 @@ -(* -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 gas. -Require memory. -Require stack. diff --git a/coq/translation/vm/instructions/stack.v b/coq/translation/vm/instructions/stack.v deleted file mode 100644 index 03a464f8c2..0000000000 --- a/coq/translation/vm/instructions/stack.v +++ /dev/null @@ -1,19 +0,0 @@ -(* -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 exceptions. -Require gas. -Require memory. diff --git a/coq/translation/vm/instructions/storage.v b/coq/translation/vm/instructions/storage.v deleted file mode 100644 index d7c600ac9a..0000000000 --- a/coq/translation/vm/instructions/storage.v +++ /dev/null @@ -1,19 +0,0 @@ -(* -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 state. -Require exceptions. -Require gas. -Require stack. diff --git a/coq/translation/vm/instructions/system.v b/coq/translation/vm/instructions/system.v deleted file mode 100644 index 27a34c527d..0000000000 --- a/coq/translation/vm/instructions/system.v +++ /dev/null @@ -1,24 +0,0 @@ -(* -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 fork_types. -Require state. -Require utils.address. -Require exceptions. -Require gas. -Require memory. -Require stack. diff --git a/coq/translation/vm/interpreter.v b/coq/translation/vm/interpreter.v deleted file mode 100644 index b093bdbc21..0000000000 --- a/coq/translation/vm/interpreter.v +++ /dev/null @@ -1,28 +0,0 @@ -(* -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 blocks. -Require fork_types. -Require state. -Require vm. -Require vm.gas. -Require vm.precompiled_contracts.mapping. -Require exceptions. -Require instructions. -Require runtime. diff --git a/coq/translation/vm/memory.v b/coq/translation/vm/memory.v deleted file mode 100644 index 6c7452b03c..0000000000 --- a/coq/translation/vm/memory.v +++ /dev/null @@ -1,17 +0,0 @@ -(* -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. diff --git a/coq/translation/vm/precompiled_contracts/alt_bn128.v b/coq/translation/vm/precompiled_contracts/alt_bn128.v deleted file mode 100644 index e7280f928c..0000000000 --- a/coq/translation/vm/precompiled_contracts/alt_bn128.v +++ /dev/null @@ -1,20 +0,0 @@ -(* -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 vm. -Require vm.gas. -Require vm.memory. -Require exceptions. diff --git a/coq/translation/vm/precompiled_contracts/blake2f.v b/coq/translation/vm/precompiled_contracts/blake2f.v deleted file mode 100644 index 9fe88931a3..0000000000 --- a/coq/translation/vm/precompiled_contracts/blake2f.v +++ /dev/null @@ -1,18 +0,0 @@ -(* -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 vm. -Require vm.gas. -Require exceptions. diff --git a/coq/translation/vm/precompiled_contracts/ecrecover.v b/coq/translation/vm/precompiled_contracts/ecrecover.v deleted file mode 100644 index c2a5513b6a..0000000000 --- a/coq/translation/vm/precompiled_contracts/ecrecover.v +++ /dev/null @@ -1,21 +0,0 @@ -(* -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 vm. -Require vm.gas. -Require vm.memory. diff --git a/coq/translation/vm/precompiled_contracts/identity.v b/coq/translation/vm/precompiled_contracts/identity.v deleted file mode 100644 index d4ff1d30e2..0000000000 --- a/coq/translation/vm/precompiled_contracts/identity.v +++ /dev/null @@ -1,18 +0,0 @@ -(* -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 vm. -Require vm.gas. diff --git a/coq/translation/vm/precompiled_contracts/mapping.v b/coq/translation/vm/precompiled_contracts/mapping.v deleted file mode 100644 index 572105c4fb..0000000000 --- a/coq/translation/vm/precompiled_contracts/mapping.v +++ /dev/null @@ -1,24 +0,0 @@ -(* -Precompiled Contract Addresses -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. contents:: Table of Contents - :backlinks: none - :local: - -Introduction ------------- - -Mapping of precompiled contracts their implementations. -*) - -Require typing. -Require fork_types. -Require alt_bn128. -Require blake2f. -Require ecrecover. -Require identity. -Require modexp. -Require point_evaluation. -Require ripemd160. -Require sha256. diff --git a/coq/translation/vm/precompiled_contracts/modexp.v b/coq/translation/vm/precompiled_contracts/modexp.v deleted file mode 100644 index 39b7b43c10..0000000000 --- a/coq/translation/vm/precompiled_contracts/modexp.v +++ /dev/null @@ -1,19 +0,0 @@ -(* -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 vm. -Require vm.gas. -Require memory. diff --git a/coq/translation/vm/precompiled_contracts/point_evaluation.v b/coq/translation/vm/precompiled_contracts/point_evaluation.v deleted file mode 100644 index a3eea74ad1..0000000000 --- a/coq/translation/vm/precompiled_contracts/point_evaluation.v +++ /dev/null @@ -1,20 +0,0 @@ -(* -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 vm. -Require vm.exceptions. -Require vm.gas. diff --git a/coq/translation/vm/precompiled_contracts/ripemd160.v b/coq/translation/vm/precompiled_contracts/ripemd160.v deleted file mode 100644 index ca9692600a..0000000000 --- a/coq/translation/vm/precompiled_contracts/ripemd160.v +++ /dev/null @@ -1,19 +0,0 @@ -(* -Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. contents:: Table of Contents - :backlinks: none - :local: - -Introduction ------------- - -Implementation of the `RIPEMD160` precompiled contract. -*) - -Require ethereum_types.numeric. -Require ethereum.utils.byte. -Require ethereum.utils.numeric. -Require vm. -Require vm.gas. diff --git a/coq/translation/vm/precompiled_contracts/sha256.v b/coq/translation/vm/precompiled_contracts/sha256.v deleted file mode 100644 index e62d067223..0000000000 --- a/coq/translation/vm/precompiled_contracts/sha256.v +++ /dev/null @@ -1,18 +0,0 @@ -(* -Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -.. contents:: Table of Contents - :backlinks: none - :local: - -Introduction ------------- - -Implementation of the `SHA256` precompiled contract. -*) - -Require ethereum_types.numeric. -Require ethereum.utils.numeric. -Require vm. -Require vm.gas. diff --git a/coq/translation/vm/runtime.v b/coq/translation/vm/runtime.v deleted file mode 100644 index 38094eefa0..0000000000 --- a/coq/translation/vm/runtime.v +++ /dev/null @@ -1,17 +0,0 @@ -(* -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 instructions. diff --git a/coq/translation/vm/stack.v b/coq/translation/vm/stack.v deleted file mode 100644 index d9409b7870..0000000000 --- a/coq/translation/vm/stack.v +++ /dev/null @@ -1,17 +0,0 @@ -(* -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 exceptions. From 2b9bb4cb344a7e845f0ec3ba7837c780e7e93b7e Mon Sep 17 00:00:00 2001 From: Guillaume Claret Date: Mon, 30 Dec 2024 10:28:33 +0100 Subject: [PATCH 3/3] wip --- coq/ethereum/__init__.v | 1 + coq/ethereum/arrow_glacier/__init__.v | 1 + coq/ethereum/arrow_glacier/blocks.v | 7 +- coq/ethereum/arrow_glacier/bloom.v | 21 +- coq/ethereum/arrow_glacier/exceptions.v | 1 + coq/ethereum/arrow_glacier/fork.v | 577 +- coq/ethereum/arrow_glacier/fork_types.v | 8 +- coq/ethereum/arrow_glacier/state.v | 285 +- coq/ethereum/arrow_glacier/transactions.v | 14 +- coq/ethereum/arrow_glacier/trie.v | 121 +- coq/ethereum/arrow_glacier/utils/__init__.v | 1 + coq/ethereum/arrow_glacier/utils/address.v | 68 +- .../arrow_glacier/utils/hexadecimal.v | 15 +- coq/ethereum/arrow_glacier/utils/message.v | 41 +- coq/ethereum/arrow_glacier/vm/__init__.v | 57 +- coq/ethereum/arrow_glacier/vm/exceptions.v | 1 + coq/ethereum/arrow_glacier/vm/gas.v | 94 +- .../arrow_glacier/vm/instructions/__init__.v | 1 + .../vm/instructions/arithmetic.v | 542 +- .../arrow_glacier/vm/instructions/bitwise.v | 308 +- .../arrow_glacier/vm/instructions/block.v | 188 +- .../vm/instructions/comparison.v | 300 +- .../vm/instructions/control_flow.v | 128 +- .../vm/instructions/environment.v | 784 +- .../arrow_glacier/vm/instructions/keccak.v | 90 +- .../arrow_glacier/vm/instructions/log.v | 66 +- .../arrow_glacier/vm/instructions/memory.v | 212 +- .../arrow_glacier/vm/instructions/stack.v | 112 +- .../arrow_glacier/vm/instructions/storage.v | 128 +- .../arrow_glacier/vm/instructions/system.v | 1056 +-- coq/ethereum/arrow_glacier/vm/interpreter.v | 142 +- coq/ethereum/arrow_glacier/vm/memory.v | 13 +- .../vm/precompiled_contracts/__init__.v | 3 +- .../vm/precompiled_contracts/alt_bn128.v | 295 +- .../vm/precompiled_contracts/blake2f.v | 25 +- .../vm/precompiled_contracts/ecrecover.v | 125 +- .../vm/precompiled_contracts/identity.v | 21 +- .../vm/precompiled_contracts/mapping.v | 18 +- .../vm/precompiled_contracts/modexp.v | 241 +- .../vm/precompiled_contracts/ripemd160.v | 41 +- .../vm/precompiled_contracts/sha256.v | 17 +- coq/ethereum/arrow_glacier/vm/runtime.v | 23 +- coq/ethereum/arrow_glacier/vm/stack.v | 11 +- coq/ethereum/berlin/__init__.v | 1 + coq/ethereum/berlin/blocks.v | 7 +- coq/ethereum/berlin/bloom.v | 21 +- coq/ethereum/berlin/exceptions.v | 1 + coq/ethereum/berlin/fork.v | 519 +- coq/ethereum/berlin/fork_types.v | 8 +- coq/ethereum/berlin/state.v | 285 +- coq/ethereum/berlin/transactions.v | 14 +- coq/ethereum/berlin/trie.v | 121 +- coq/ethereum/berlin/utils/__init__.v | 1 + coq/ethereum/berlin/utils/address.v | 68 +- coq/ethereum/berlin/utils/hexadecimal.v | 15 +- coq/ethereum/berlin/utils/message.v | 41 +- coq/ethereum/berlin/vm/__init__.v | 57 +- coq/ethereum/berlin/vm/exceptions.v | 1 + coq/ethereum/berlin/vm/gas.v | 94 +- .../berlin/vm/instructions/__init__.v | 1 + .../berlin/vm/instructions/arithmetic.v | 542 +- coq/ethereum/berlin/vm/instructions/bitwise.v | 308 +- coq/ethereum/berlin/vm/instructions/block.v | 188 +- .../berlin/vm/instructions/comparison.v | 300 +- .../berlin/vm/instructions/control_flow.v | 128 +- .../berlin/vm/instructions/environment.v | 760 +- coq/ethereum/berlin/vm/instructions/keccak.v | 90 +- coq/ethereum/berlin/vm/instructions/log.v | 66 +- coq/ethereum/berlin/vm/instructions/memory.v | 212 +- coq/ethereum/berlin/vm/instructions/stack.v | 112 +- coq/ethereum/berlin/vm/instructions/storage.v | 128 +- coq/ethereum/berlin/vm/instructions/system.v | 1064 +-- coq/ethereum/berlin/vm/interpreter.v | 142 +- coq/ethereum/berlin/vm/memory.v | 13 +- .../vm/precompiled_contracts/__init__.v | 3 +- .../vm/precompiled_contracts/alt_bn128.v | 295 +- .../berlin/vm/precompiled_contracts/blake2f.v | 25 +- .../vm/precompiled_contracts/ecrecover.v | 125 +- .../vm/precompiled_contracts/identity.v | 21 +- .../berlin/vm/precompiled_contracts/mapping.v | 18 +- .../berlin/vm/precompiled_contracts/modexp.v | 241 +- .../vm/precompiled_contracts/ripemd160.v | 41 +- .../berlin/vm/precompiled_contracts/sha256.v | 17 +- coq/ethereum/berlin/vm/runtime.v | 23 +- coq/ethereum/berlin/vm/stack.v | 11 +- coq/ethereum/byzantium/__init__.v | 1 + coq/ethereum/byzantium/blocks.v | 7 +- coq/ethereum/byzantium/bloom.v | 21 +- coq/ethereum/byzantium/fork.v | 493 +- coq/ethereum/byzantium/fork_types.v | 8 +- coq/ethereum/byzantium/state.v | 265 +- coq/ethereum/byzantium/transactions.v | 3 +- coq/ethereum/byzantium/trie.v | 121 +- coq/ethereum/byzantium/utils/__init__.v | 1 + coq/ethereum/byzantium/utils/address.v | 38 +- coq/ethereum/byzantium/utils/hexadecimal.v | 15 +- coq/ethereum/byzantium/utils/message.v | 13 +- coq/ethereum/byzantium/vm/__init__.v | 45 +- coq/ethereum/byzantium/vm/exceptions.v | 1 + coq/ethereum/byzantium/vm/gas.v | 94 +- .../byzantium/vm/instructions/__init__.v | 1 + .../byzantium/vm/instructions/arithmetic.v | 542 +- .../byzantium/vm/instructions/bitwise.v | 188 +- .../byzantium/vm/instructions/block.v | 164 +- .../byzantium/vm/instructions/comparison.v | 300 +- .../byzantium/vm/instructions/control_flow.v | 128 +- .../byzantium/vm/instructions/environment.v | 694 +- .../byzantium/vm/instructions/keccak.v | 90 +- coq/ethereum/byzantium/vm/instructions/log.v | 66 +- .../byzantium/vm/instructions/memory.v | 212 +- .../byzantium/vm/instructions/stack.v | 112 +- .../byzantium/vm/instructions/storage.v | 112 +- .../byzantium/vm/instructions/system.v | 878 ++- coq/ethereum/byzantium/vm/interpreter.v | 134 +- coq/ethereum/byzantium/vm/memory.v | 13 +- .../vm/precompiled_contracts/__init__.v | 3 +- .../vm/precompiled_contracts/alt_bn128.v | 295 +- .../vm/precompiled_contracts/ecrecover.v | 125 +- .../vm/precompiled_contracts/identity.v | 21 +- .../vm/precompiled_contracts/mapping.v | 16 +- .../vm/precompiled_contracts/modexp.v | 237 +- .../vm/precompiled_contracts/ripemd160.v | 41 +- .../vm/precompiled_contracts/sha256.v | 17 +- coq/ethereum/byzantium/vm/runtime.v | 23 +- coq/ethereum/byzantium/vm/stack.v | 11 +- coq/ethereum/cancun/__init__.v | 1 + coq/ethereum/cancun/blocks.v | 7 +- coq/ethereum/cancun/bloom.v | 21 +- coq/ethereum/cancun/exceptions.v | 1 + coq/ethereum/cancun/fork.v | 533 +- coq/ethereum/cancun/fork_types.v | 8 +- coq/ethereum/cancun/state.v | 343 +- coq/ethereum/cancun/transactions.v | 14 +- coq/ethereum/cancun/trie.v | 121 +- coq/ethereum/cancun/utils/__init__.v | 1 + coq/ethereum/cancun/utils/address.v | 68 +- coq/ethereum/cancun/utils/hexadecimal.v | 15 +- coq/ethereum/cancun/utils/message.v | 41 +- coq/ethereum/cancun/vm/__init__.v | 57 +- coq/ethereum/cancun/vm/exceptions.v | 1 + coq/ethereum/cancun/vm/gas.v | 138 +- .../cancun/vm/instructions/__init__.v | 1 + .../cancun/vm/instructions/arithmetic.v | 542 +- coq/ethereum/cancun/vm/instructions/bitwise.v | 308 +- coq/ethereum/cancun/vm/instructions/block.v | 188 +- .../cancun/vm/instructions/comparison.v | 300 +- .../cancun/vm/instructions/control_flow.v | 128 +- .../cancun/vm/instructions/environment.v | 848 ++- coq/ethereum/cancun/vm/instructions/keccak.v | 90 +- coq/ethereum/cancun/vm/instructions/log.v | 66 +- coq/ethereum/cancun/vm/instructions/memory.v | 294 +- coq/ethereum/cancun/vm/instructions/stack.v | 108 +- coq/ethereum/cancun/vm/instructions/storage.v | 228 +- coq/ethereum/cancun/vm/instructions/system.v | 1060 +-- coq/ethereum/cancun/vm/interpreter.v | 146 +- coq/ethereum/cancun/vm/memory.v | 13 +- .../vm/precompiled_contracts/__init__.v | 3 +- .../vm/precompiled_contracts/alt_bn128.v | 295 +- .../cancun/vm/precompiled_contracts/blake2f.v | 25 +- .../vm/precompiled_contracts/ecrecover.v | 125 +- .../vm/precompiled_contracts/identity.v | 21 +- .../cancun/vm/precompiled_contracts/mapping.v | 20 +- .../cancun/vm/precompiled_contracts/modexp.v | 241 +- .../precompiled_contracts/point_evaluation.v | 55 +- .../vm/precompiled_contracts/ripemd160.v | 41 +- .../cancun/vm/precompiled_contracts/sha256.v | 17 +- coq/ethereum/cancun/vm/runtime.v | 23 +- coq/ethereum/cancun/vm/stack.v | 11 +- coq/ethereum/constantinople/__init__.v | 1 + coq/ethereum/constantinople/blocks.v | 7 +- coq/ethereum/constantinople/bloom.v | 21 +- coq/ethereum/constantinople/fork.v | 493 +- coq/ethereum/constantinople/fork_types.v | 8 +- coq/ethereum/constantinople/state.v | 265 +- coq/ethereum/constantinople/transactions.v | 3 +- coq/ethereum/constantinople/trie.v | 121 +- coq/ethereum/constantinople/utils/__init__.v | 1 + coq/ethereum/constantinople/utils/address.v | 68 +- .../constantinople/utils/hexadecimal.v | 15 +- coq/ethereum/constantinople/utils/message.v | 13 +- coq/ethereum/constantinople/vm/__init__.v | 45 +- coq/ethereum/constantinople/vm/exceptions.v | 1 + coq/ethereum/constantinople/vm/gas.v | 94 +- .../constantinople/vm/instructions/__init__.v | 1 + .../vm/instructions/arithmetic.v | 542 +- .../constantinople/vm/instructions/bitwise.v | 308 +- .../constantinople/vm/instructions/block.v | 164 +- .../vm/instructions/comparison.v | 300 +- .../vm/instructions/control_flow.v | 128 +- .../vm/instructions/environment.v | 740 +- .../constantinople/vm/instructions/keccak.v | 90 +- .../constantinople/vm/instructions/log.v | 66 +- .../constantinople/vm/instructions/memory.v | 212 +- .../constantinople/vm/instructions/stack.v | 112 +- .../constantinople/vm/instructions/storage.v | 112 +- .../constantinople/vm/instructions/system.v | 1058 +-- coq/ethereum/constantinople/vm/interpreter.v | 134 +- coq/ethereum/constantinople/vm/memory.v | 13 +- .../vm/precompiled_contracts/__init__.v | 3 +- .../vm/precompiled_contracts/alt_bn128.v | 295 +- .../vm/precompiled_contracts/ecrecover.v | 125 +- .../vm/precompiled_contracts/identity.v | 21 +- .../vm/precompiled_contracts/mapping.v | 16 +- .../vm/precompiled_contracts/modexp.v | 237 +- .../vm/precompiled_contracts/ripemd160.v | 41 +- .../vm/precompiled_contracts/sha256.v | 17 +- coq/ethereum/constantinople/vm/runtime.v | 23 +- coq/ethereum/constantinople/vm/stack.v | 11 +- coq/ethereum/crypto/__init__.v | 1 + coq/ethereum/crypto/alt_bn128.v | 82 +- coq/ethereum/crypto/blake2.v | 9 +- coq/ethereum/crypto/elliptic_curve.v | 43 +- coq/ethereum/crypto/finite_field.v | 1 + coq/ethereum/crypto/hash.v | 21 +- coq/ethereum/crypto/kzg.v | 113 +- coq/ethereum/dao_fork/__init__.v | 1 + coq/ethereum/dao_fork/blocks.v | 7 +- coq/ethereum/dao_fork/bloom.v | 21 +- coq/ethereum/dao_fork/dao.v | 9 +- coq/ethereum/dao_fork/fork.v | 511 +- coq/ethereum/dao_fork/fork_types.v | 8 +- coq/ethereum/dao_fork/state.v | 223 +- coq/ethereum/dao_fork/transactions.v | 3 +- coq/ethereum/dao_fork/trie.v | 121 +- coq/ethereum/dao_fork/utils/__init__.v | 1 + coq/ethereum/dao_fork/utils/address.v | 38 +- coq/ethereum/dao_fork/utils/hexadecimal.v | 15 +- coq/ethereum/dao_fork/utils/message.v | 13 +- coq/ethereum/dao_fork/vm/__init__.v | 37 +- coq/ethereum/dao_fork/vm/exceptions.v | 1 + coq/ethereum/dao_fork/vm/gas.v | 92 +- .../dao_fork/vm/instructions/__init__.v | 1 + .../dao_fork/vm/instructions/arithmetic.v | 542 +- .../dao_fork/vm/instructions/bitwise.v | 188 +- coq/ethereum/dao_fork/vm/instructions/block.v | 164 +- .../dao_fork/vm/instructions/comparison.v | 300 +- .../dao_fork/vm/instructions/control_flow.v | 128 +- .../dao_fork/vm/instructions/environment.v | 592 +- .../dao_fork/vm/instructions/keccak.v | 90 +- coq/ethereum/dao_fork/vm/instructions/log.v | 64 +- .../dao_fork/vm/instructions/memory.v | 212 +- coq/ethereum/dao_fork/vm/instructions/stack.v | 112 +- .../dao_fork/vm/instructions/storage.v | 110 +- .../dao_fork/vm/instructions/system.v | 630 +- coq/ethereum/dao_fork/vm/interpreter.v | 126 +- coq/ethereum/dao_fork/vm/memory.v | 13 +- .../vm/precompiled_contracts/__init__.v | 3 +- .../vm/precompiled_contracts/ecrecover.v | 125 +- .../vm/precompiled_contracts/identity.v | 21 +- .../vm/precompiled_contracts/mapping.v | 12 +- .../vm/precompiled_contracts/ripemd160.v | 41 +- .../vm/precompiled_contracts/sha256.v | 17 +- coq/ethereum/dao_fork/vm/runtime.v | 23 +- coq/ethereum/dao_fork/vm/stack.v | 11 +- coq/ethereum/ethash.v | 189 +- coq/ethereum/exceptions.v | 1 + coq/ethereum/fork_criteria.v | 1 + coq/ethereum/frontier/__init__.v | 1 + coq/ethereum/frontier/blocks.v | 7 +- coq/ethereum/frontier/bloom.v | 21 +- coq/ethereum/frontier/fork.v | 495 +- coq/ethereum/frontier/fork_types.v | 8 +- coq/ethereum/frontier/state.v | 223 +- coq/ethereum/frontier/transactions.v | 3 +- coq/ethereum/frontier/trie.v | 121 +- coq/ethereum/frontier/utils/__init__.v | 1 + coq/ethereum/frontier/utils/address.v | 38 +- coq/ethereum/frontier/utils/hexadecimal.v | 15 +- coq/ethereum/frontier/utils/message.v | 13 +- coq/ethereum/frontier/vm/__init__.v | 37 +- coq/ethereum/frontier/vm/exceptions.v | 1 + coq/ethereum/frontier/vm/gas.v | 92 +- .../frontier/vm/instructions/__init__.v | 1 + .../frontier/vm/instructions/arithmetic.v | 542 +- .../frontier/vm/instructions/bitwise.v | 188 +- coq/ethereum/frontier/vm/instructions/block.v | 164 +- .../frontier/vm/instructions/comparison.v | 300 +- .../frontier/vm/instructions/control_flow.v | 128 +- .../frontier/vm/instructions/environment.v | 592 +- .../frontier/vm/instructions/keccak.v | 90 +- coq/ethereum/frontier/vm/instructions/log.v | 64 +- .../frontier/vm/instructions/memory.v | 212 +- coq/ethereum/frontier/vm/instructions/stack.v | 112 +- .../frontier/vm/instructions/storage.v | 110 +- .../frontier/vm/instructions/system.v | 522 +- coq/ethereum/frontier/vm/interpreter.v | 126 +- coq/ethereum/frontier/vm/memory.v | 13 +- .../vm/precompiled_contracts/__init__.v | 3 +- .../vm/precompiled_contracts/ecrecover.v | 125 +- .../vm/precompiled_contracts/identity.v | 21 +- .../vm/precompiled_contracts/mapping.v | 12 +- .../vm/precompiled_contracts/ripemd160.v | 41 +- .../vm/precompiled_contracts/sha256.v | 17 +- coq/ethereum/frontier/vm/runtime.v | 23 +- coq/ethereum/frontier/vm/stack.v | 11 +- coq/ethereum/genesis.v | 67 +- coq/ethereum/gray_glacier/__init__.v | 1 + coq/ethereum/gray_glacier/blocks.v | 7 +- coq/ethereum/gray_glacier/bloom.v | 21 +- coq/ethereum/gray_glacier/exceptions.v | 1 + coq/ethereum/gray_glacier/fork.v | 577 +- coq/ethereum/gray_glacier/fork_types.v | 8 +- coq/ethereum/gray_glacier/state.v | 285 +- coq/ethereum/gray_glacier/transactions.v | 14 +- coq/ethereum/gray_glacier/trie.v | 121 +- coq/ethereum/gray_glacier/utils/__init__.v | 1 + coq/ethereum/gray_glacier/utils/address.v | 68 +- coq/ethereum/gray_glacier/utils/hexadecimal.v | 15 +- coq/ethereum/gray_glacier/utils/message.v | 41 +- coq/ethereum/gray_glacier/vm/__init__.v | 57 +- coq/ethereum/gray_glacier/vm/exceptions.v | 1 + coq/ethereum/gray_glacier/vm/gas.v | 94 +- .../gray_glacier/vm/instructions/__init__.v | 1 + .../gray_glacier/vm/instructions/arithmetic.v | 542 +- .../gray_glacier/vm/instructions/bitwise.v | 308 +- .../gray_glacier/vm/instructions/block.v | 188 +- .../gray_glacier/vm/instructions/comparison.v | 300 +- .../vm/instructions/control_flow.v | 128 +- .../vm/instructions/environment.v | 784 +- .../gray_glacier/vm/instructions/keccak.v | 90 +- .../gray_glacier/vm/instructions/log.v | 66 +- .../gray_glacier/vm/instructions/memory.v | 212 +- .../gray_glacier/vm/instructions/stack.v | 112 +- .../gray_glacier/vm/instructions/storage.v | 128 +- .../gray_glacier/vm/instructions/system.v | 1056 +-- coq/ethereum/gray_glacier/vm/interpreter.v | 142 +- coq/ethereum/gray_glacier/vm/memory.v | 13 +- .../vm/precompiled_contracts/__init__.v | 3 +- .../vm/precompiled_contracts/alt_bn128.v | 295 +- .../vm/precompiled_contracts/blake2f.v | 25 +- .../vm/precompiled_contracts/ecrecover.v | 125 +- .../vm/precompiled_contracts/identity.v | 21 +- .../vm/precompiled_contracts/mapping.v | 18 +- .../vm/precompiled_contracts/modexp.v | 241 +- .../vm/precompiled_contracts/ripemd160.v | 41 +- .../vm/precompiled_contracts/sha256.v | 17 +- coq/ethereum/gray_glacier/vm/runtime.v | 23 +- coq/ethereum/gray_glacier/vm/stack.v | 11 +- coq/ethereum/homestead/__init__.v | 1 + coq/ethereum/homestead/blocks.v | 7 +- coq/ethereum/homestead/bloom.v | 21 +- coq/ethereum/homestead/fork.v | 503 +- coq/ethereum/homestead/fork_types.v | 8 +- coq/ethereum/homestead/state.v | 223 +- coq/ethereum/homestead/transactions.v | 3 +- coq/ethereum/homestead/trie.v | 121 +- coq/ethereum/homestead/utils/__init__.v | 1 + coq/ethereum/homestead/utils/address.v | 38 +- coq/ethereum/homestead/utils/hexadecimal.v | 15 +- coq/ethereum/homestead/utils/message.v | 13 +- coq/ethereum/homestead/vm/__init__.v | 37 +- coq/ethereum/homestead/vm/exceptions.v | 1 + coq/ethereum/homestead/vm/gas.v | 92 +- .../homestead/vm/instructions/__init__.v | 1 + .../homestead/vm/instructions/arithmetic.v | 542 +- .../homestead/vm/instructions/bitwise.v | 188 +- .../homestead/vm/instructions/block.v | 164 +- .../homestead/vm/instructions/comparison.v | 300 +- .../homestead/vm/instructions/control_flow.v | 128 +- .../homestead/vm/instructions/environment.v | 592 +- .../homestead/vm/instructions/keccak.v | 90 +- coq/ethereum/homestead/vm/instructions/log.v | 64 +- .../homestead/vm/instructions/memory.v | 212 +- .../homestead/vm/instructions/stack.v | 112 +- .../homestead/vm/instructions/storage.v | 110 +- .../homestead/vm/instructions/system.v | 630 +- coq/ethereum/homestead/vm/interpreter.v | 126 +- coq/ethereum/homestead/vm/memory.v | 13 +- .../vm/precompiled_contracts/__init__.v | 3 +- .../vm/precompiled_contracts/ecrecover.v | 125 +- .../vm/precompiled_contracts/identity.v | 21 +- .../vm/precompiled_contracts/mapping.v | 12 +- .../vm/precompiled_contracts/ripemd160.v | 41 +- .../vm/precompiled_contracts/sha256.v | 17 +- coq/ethereum/homestead/vm/runtime.v | 23 +- coq/ethereum/homestead/vm/stack.v | 11 +- coq/ethereum/istanbul/__init__.v | 1 + coq/ethereum/istanbul/blocks.v | 7 +- coq/ethereum/istanbul/bloom.v | 21 +- coq/ethereum/istanbul/fork.v | 493 +- coq/ethereum/istanbul/fork_types.v | 8 +- coq/ethereum/istanbul/state.v | 285 +- coq/ethereum/istanbul/transactions.v | 3 +- coq/ethereum/istanbul/trie.v | 121 +- coq/ethereum/istanbul/utils/__init__.v | 1 + coq/ethereum/istanbul/utils/address.v | 68 +- coq/ethereum/istanbul/utils/hexadecimal.v | 15 +- coq/ethereum/istanbul/utils/message.v | 13 +- coq/ethereum/istanbul/vm/__init__.v | 45 +- coq/ethereum/istanbul/vm/exceptions.v | 1 + coq/ethereum/istanbul/vm/gas.v | 94 +- .../istanbul/vm/instructions/__init__.v | 1 + .../istanbul/vm/instructions/arithmetic.v | 542 +- .../istanbul/vm/instructions/bitwise.v | 308 +- coq/ethereum/istanbul/vm/instructions/block.v | 188 +- .../istanbul/vm/instructions/comparison.v | 300 +- .../istanbul/vm/instructions/control_flow.v | 128 +- .../istanbul/vm/instructions/environment.v | 774 +- .../istanbul/vm/instructions/keccak.v | 90 +- coq/ethereum/istanbul/vm/instructions/log.v | 66 +- .../istanbul/vm/instructions/memory.v | 212 +- coq/ethereum/istanbul/vm/instructions/stack.v | 112 +- .../istanbul/vm/instructions/storage.v | 124 +- .../istanbul/vm/instructions/system.v | 1058 +-- coq/ethereum/istanbul/vm/interpreter.v | 142 +- coq/ethereum/istanbul/vm/memory.v | 13 +- .../vm/precompiled_contracts/__init__.v | 3 +- .../vm/precompiled_contracts/alt_bn128.v | 295 +- .../vm/precompiled_contracts/blake2f.v | 25 +- .../vm/precompiled_contracts/ecrecover.v | 125 +- .../vm/precompiled_contracts/identity.v | 21 +- .../vm/precompiled_contracts/mapping.v | 18 +- .../vm/precompiled_contracts/modexp.v | 237 +- .../vm/precompiled_contracts/ripemd160.v | 41 +- .../vm/precompiled_contracts/sha256.v | 17 +- coq/ethereum/istanbul/vm/runtime.v | 23 +- coq/ethereum/istanbul/vm/stack.v | 11 +- coq/ethereum/london/__init__.v | 1 + coq/ethereum/london/blocks.v | 7 +- coq/ethereum/london/bloom.v | 21 +- coq/ethereum/london/exceptions.v | 1 + coq/ethereum/london/fork.v | 555 +- coq/ethereum/london/fork_types.v | 8 +- coq/ethereum/london/state.v | 285 +- coq/ethereum/london/transactions.v | 14 +- coq/ethereum/london/trie.v | 121 +- coq/ethereum/london/utils/__init__.v | 1 + coq/ethereum/london/utils/address.v | 68 +- coq/ethereum/london/utils/hexadecimal.v | 15 +- coq/ethereum/london/utils/message.v | 41 +- coq/ethereum/london/vm/__init__.v | 57 +- coq/ethereum/london/vm/exceptions.v | 1 + coq/ethereum/london/vm/gas.v | 94 +- .../london/vm/instructions/__init__.v | 1 + .../london/vm/instructions/arithmetic.v | 542 +- coq/ethereum/london/vm/instructions/bitwise.v | 308 +- coq/ethereum/london/vm/instructions/block.v | 188 +- .../london/vm/instructions/comparison.v | 300 +- .../london/vm/instructions/control_flow.v | 128 +- .../london/vm/instructions/environment.v | 784 +- coq/ethereum/london/vm/instructions/keccak.v | 90 +- coq/ethereum/london/vm/instructions/log.v | 66 +- coq/ethereum/london/vm/instructions/memory.v | 212 +- coq/ethereum/london/vm/instructions/stack.v | 112 +- coq/ethereum/london/vm/instructions/storage.v | 128 +- coq/ethereum/london/vm/instructions/system.v | 1056 +-- coq/ethereum/london/vm/interpreter.v | 142 +- coq/ethereum/london/vm/memory.v | 13 +- .../vm/precompiled_contracts/__init__.v | 3 +- .../vm/precompiled_contracts/alt_bn128.v | 295 +- .../london/vm/precompiled_contracts/blake2f.v | 25 +- .../vm/precompiled_contracts/ecrecover.v | 125 +- .../vm/precompiled_contracts/identity.v | 21 +- .../london/vm/precompiled_contracts/mapping.v | 18 +- .../london/vm/precompiled_contracts/modexp.v | 241 +- .../vm/precompiled_contracts/ripemd160.v | 41 +- .../london/vm/precompiled_contracts/sha256.v | 17 +- coq/ethereum/london/vm/runtime.v | 23 +- coq/ethereum/london/vm/stack.v | 11 +- coq/ethereum/muir_glacier/__init__.v | 1 + coq/ethereum/muir_glacier/blocks.v | 7 +- coq/ethereum/muir_glacier/bloom.v | 21 +- coq/ethereum/muir_glacier/fork.v | 493 +- coq/ethereum/muir_glacier/fork_types.v | 8 +- coq/ethereum/muir_glacier/state.v | 285 +- coq/ethereum/muir_glacier/transactions.v | 3 +- coq/ethereum/muir_glacier/trie.v | 121 +- coq/ethereum/muir_glacier/utils/__init__.v | 1 + coq/ethereum/muir_glacier/utils/address.v | 68 +- coq/ethereum/muir_glacier/utils/hexadecimal.v | 15 +- coq/ethereum/muir_glacier/utils/message.v | 13 +- coq/ethereum/muir_glacier/vm/__init__.v | 45 +- coq/ethereum/muir_glacier/vm/exceptions.v | 1 + coq/ethereum/muir_glacier/vm/gas.v | 94 +- .../muir_glacier/vm/instructions/__init__.v | 1 + .../muir_glacier/vm/instructions/arithmetic.v | 542 +- .../muir_glacier/vm/instructions/bitwise.v | 308 +- .../muir_glacier/vm/instructions/block.v | 188 +- .../muir_glacier/vm/instructions/comparison.v | 300 +- .../vm/instructions/control_flow.v | 128 +- .../vm/instructions/environment.v | 774 +- .../muir_glacier/vm/instructions/keccak.v | 90 +- .../muir_glacier/vm/instructions/log.v | 66 +- .../muir_glacier/vm/instructions/memory.v | 212 +- .../muir_glacier/vm/instructions/stack.v | 112 +- .../muir_glacier/vm/instructions/storage.v | 124 +- .../muir_glacier/vm/instructions/system.v | 1058 +-- coq/ethereum/muir_glacier/vm/interpreter.v | 142 +- coq/ethereum/muir_glacier/vm/memory.v | 13 +- .../vm/precompiled_contracts/__init__.v | 3 +- .../vm/precompiled_contracts/alt_bn128.v | 295 +- .../vm/precompiled_contracts/blake2f.v | 25 +- .../vm/precompiled_contracts/ecrecover.v | 125 +- .../vm/precompiled_contracts/identity.v | 21 +- .../vm/precompiled_contracts/mapping.v | 18 +- .../vm/precompiled_contracts/modexp.v | 237 +- .../vm/precompiled_contracts/ripemd160.v | 41 +- .../vm/precompiled_contracts/sha256.v | 17 +- coq/ethereum/muir_glacier/vm/runtime.v | 23 +- coq/ethereum/muir_glacier/vm/stack.v | 11 +- coq/ethereum/paris/__init__.v | 1 + coq/ethereum/paris/blocks.v | 7 +- coq/ethereum/paris/bloom.v | 21 +- coq/ethereum/paris/exceptions.v | 1 + coq/ethereum/paris/fork.v | 421 +- coq/ethereum/paris/fork_types.v | 8 +- coq/ethereum/paris/state.v | 275 +- coq/ethereum/paris/transactions.v | 14 +- coq/ethereum/paris/trie.v | 121 +- coq/ethereum/paris/utils/__init__.v | 1 + coq/ethereum/paris/utils/address.v | 68 +- coq/ethereum/paris/utils/hexadecimal.v | 15 +- coq/ethereum/paris/utils/message.v | 41 +- coq/ethereum/paris/vm/__init__.v | 57 +- coq/ethereum/paris/vm/exceptions.v | 1 + coq/ethereum/paris/vm/gas.v | 94 +- coq/ethereum/paris/vm/instructions/__init__.v | 1 + .../paris/vm/instructions/arithmetic.v | 542 +- coq/ethereum/paris/vm/instructions/bitwise.v | 308 +- coq/ethereum/paris/vm/instructions/block.v | 188 +- .../paris/vm/instructions/comparison.v | 300 +- .../paris/vm/instructions/control_flow.v | 128 +- .../paris/vm/instructions/environment.v | 784 +- coq/ethereum/paris/vm/instructions/keccak.v | 90 +- coq/ethereum/paris/vm/instructions/log.v | 66 +- coq/ethereum/paris/vm/instructions/memory.v | 212 +- coq/ethereum/paris/vm/instructions/stack.v | 112 +- coq/ethereum/paris/vm/instructions/storage.v | 128 +- coq/ethereum/paris/vm/instructions/system.v | 1056 +-- coq/ethereum/paris/vm/interpreter.v | 142 +- coq/ethereum/paris/vm/memory.v | 13 +- .../paris/vm/precompiled_contracts/__init__.v | 3 +- .../vm/precompiled_contracts/alt_bn128.v | 295 +- .../paris/vm/precompiled_contracts/blake2f.v | 25 +- .../vm/precompiled_contracts/ecrecover.v | 125 +- .../paris/vm/precompiled_contracts/identity.v | 21 +- .../paris/vm/precompiled_contracts/mapping.v | 18 +- .../paris/vm/precompiled_contracts/modexp.v | 241 +- .../vm/precompiled_contracts/ripemd160.v | 41 +- .../paris/vm/precompiled_contracts/sha256.v | 17 +- coq/ethereum/paris/vm/runtime.v | 23 +- coq/ethereum/paris/vm/stack.v | 11 +- coq/ethereum/rlp.v | 203 +- coq/ethereum/shanghai/__init__.v | 1 + coq/ethereum/shanghai/blocks.v | 7 +- coq/ethereum/shanghai/bloom.v | 21 +- coq/ethereum/shanghai/exceptions.v | 1 + coq/ethereum/shanghai/fork.v | 433 +- coq/ethereum/shanghai/fork_types.v | 8 +- coq/ethereum/shanghai/state.v | 289 +- coq/ethereum/shanghai/transactions.v | 14 +- coq/ethereum/shanghai/trie.v | 121 +- coq/ethereum/shanghai/utils/__init__.v | 1 + coq/ethereum/shanghai/utils/address.v | 68 +- coq/ethereum/shanghai/utils/hexadecimal.v | 15 +- coq/ethereum/shanghai/utils/message.v | 41 +- coq/ethereum/shanghai/vm/__init__.v | 57 +- coq/ethereum/shanghai/vm/exceptions.v | 1 + coq/ethereum/shanghai/vm/gas.v | 98 +- .../shanghai/vm/instructions/__init__.v | 1 + .../shanghai/vm/instructions/arithmetic.v | 542 +- .../shanghai/vm/instructions/bitwise.v | 308 +- coq/ethereum/shanghai/vm/instructions/block.v | 188 +- .../shanghai/vm/instructions/comparison.v | 300 +- .../shanghai/vm/instructions/control_flow.v | 128 +- .../shanghai/vm/instructions/environment.v | 784 +- .../shanghai/vm/instructions/keccak.v | 90 +- coq/ethereum/shanghai/vm/instructions/log.v | 66 +- .../shanghai/vm/instructions/memory.v | 212 +- coq/ethereum/shanghai/vm/instructions/stack.v | 108 +- .../shanghai/vm/instructions/storage.v | 128 +- .../shanghai/vm/instructions/system.v | 1084 +-- coq/ethereum/shanghai/vm/interpreter.v | 142 +- coq/ethereum/shanghai/vm/memory.v | 13 +- .../vm/precompiled_contracts/__init__.v | 3 +- .../vm/precompiled_contracts/alt_bn128.v | 295 +- .../vm/precompiled_contracts/blake2f.v | 25 +- .../vm/precompiled_contracts/ecrecover.v | 125 +- .../vm/precompiled_contracts/identity.v | 21 +- .../vm/precompiled_contracts/mapping.v | 18 +- .../vm/precompiled_contracts/modexp.v | 241 +- .../vm/precompiled_contracts/ripemd160.v | 41 +- .../vm/precompiled_contracts/sha256.v | 17 +- coq/ethereum/shanghai/vm/runtime.v | 23 +- coq/ethereum/shanghai/vm/stack.v | 11 +- coq/ethereum/spurious_dragon/__init__.v | 1 + coq/ethereum/spurious_dragon/blocks.v | 7 +- coq/ethereum/spurious_dragon/bloom.v | 21 +- coq/ethereum/spurious_dragon/fork.v | 487 +- coq/ethereum/spurious_dragon/fork_types.v | 8 +- coq/ethereum/spurious_dragon/state.v | 265 +- coq/ethereum/spurious_dragon/transactions.v | 3 +- coq/ethereum/spurious_dragon/trie.v | 121 +- coq/ethereum/spurious_dragon/utils/__init__.v | 1 + coq/ethereum/spurious_dragon/utils/address.v | 38 +- .../spurious_dragon/utils/hexadecimal.v | 15 +- coq/ethereum/spurious_dragon/utils/message.v | 13 +- coq/ethereum/spurious_dragon/vm/__init__.v | 45 +- coq/ethereum/spurious_dragon/vm/exceptions.v | 1 + coq/ethereum/spurious_dragon/vm/gas.v | 94 +- .../vm/instructions/__init__.v | 1 + .../vm/instructions/arithmetic.v | 542 +- .../spurious_dragon/vm/instructions/bitwise.v | 188 +- .../spurious_dragon/vm/instructions/block.v | 164 +- .../vm/instructions/comparison.v | 300 +- .../vm/instructions/control_flow.v | 128 +- .../vm/instructions/environment.v | 592 +- .../spurious_dragon/vm/instructions/keccak.v | 90 +- .../spurious_dragon/vm/instructions/log.v | 64 +- .../spurious_dragon/vm/instructions/memory.v | 212 +- .../spurious_dragon/vm/instructions/stack.v | 112 +- .../spurious_dragon/vm/instructions/storage.v | 110 +- .../spurious_dragon/vm/instructions/system.v | 688 +- coq/ethereum/spurious_dragon/vm/interpreter.v | 134 +- coq/ethereum/spurious_dragon/vm/memory.v | 13 +- .../vm/precompiled_contracts/__init__.v | 3 +- .../vm/precompiled_contracts/ecrecover.v | 125 +- .../vm/precompiled_contracts/identity.v | 21 +- .../vm/precompiled_contracts/mapping.v | 12 +- .../vm/precompiled_contracts/ripemd160.v | 41 +- .../vm/precompiled_contracts/sha256.v | 17 +- coq/ethereum/spurious_dragon/vm/runtime.v | 23 +- coq/ethereum/spurious_dragon/vm/stack.v | 11 +- coq/ethereum/tangerine_whistle/__init__.v | 1 + coq/ethereum/tangerine_whistle/blocks.v | 7 +- coq/ethereum/tangerine_whistle/bloom.v | 21 +- coq/ethereum/tangerine_whistle/fork.v | 503 +- coq/ethereum/tangerine_whistle/fork_types.v | 8 +- coq/ethereum/tangerine_whistle/state.v | 223 +- coq/ethereum/tangerine_whistle/transactions.v | 3 +- coq/ethereum/tangerine_whistle/trie.v | 121 +- .../tangerine_whistle/utils/__init__.v | 1 + .../tangerine_whistle/utils/address.v | 38 +- .../tangerine_whistle/utils/hexadecimal.v | 15 +- .../tangerine_whistle/utils/message.v | 13 +- coq/ethereum/tangerine_whistle/vm/__init__.v | 37 +- .../tangerine_whistle/vm/exceptions.v | 1 + coq/ethereum/tangerine_whistle/vm/gas.v | 94 +- .../vm/instructions/__init__.v | 1 + .../vm/instructions/arithmetic.v | 542 +- .../vm/instructions/bitwise.v | 188 +- .../tangerine_whistle/vm/instructions/block.v | 164 +- .../vm/instructions/comparison.v | 300 +- .../vm/instructions/control_flow.v | 128 +- .../vm/instructions/environment.v | 592 +- .../vm/instructions/keccak.v | 90 +- .../tangerine_whistle/vm/instructions/log.v | 64 +- .../vm/instructions/memory.v | 212 +- .../tangerine_whistle/vm/instructions/stack.v | 112 +- .../vm/instructions/storage.v | 110 +- .../vm/instructions/system.v | 698 +- .../tangerine_whistle/vm/interpreter.v | 126 +- coq/ethereum/tangerine_whistle/vm/memory.v | 13 +- .../vm/precompiled_contracts/__init__.v | 3 +- .../vm/precompiled_contracts/ecrecover.v | 125 +- .../vm/precompiled_contracts/identity.v | 21 +- .../vm/precompiled_contracts/mapping.v | 12 +- .../vm/precompiled_contracts/ripemd160.v | 41 +- .../vm/precompiled_contracts/sha256.v | 17 +- coq/ethereum/tangerine_whistle/vm/runtime.v | 23 +- coq/ethereum/tangerine_whistle/vm/stack.v | 11 +- coq/ethereum/trace.v | 5 +- coq/ethereum/utils/__init__.v | 5 +- coq/ethereum/utils/byte.v | 9 +- coq/ethereum/utils/hexadecimal.v | 45 +- coq/ethereum/utils/numeric.v | 85 +- coq/ethereum/utils/safe_arithmetic.v | 17 +- coq/ethereum_optimized/__init__.ast | 250 + coq/ethereum_optimized/__init__.v | 82 + coq/ethereum_optimized/fork.ast | 252 + coq/ethereum_optimized/fork.v | 44 + coq/ethereum_optimized/state_db.ast | 2332 ++++++ coq/ethereum_optimized/state_db.v | 73 + coq/ethereum_optimized/utils.ast | 62 + coq/ethereum_optimized/utils.v | 24 + coq/ethereum_spec_tools/__init__.ast | 5 + coq/ethereum_spec_tools/__init__.v | 9 + coq/ethereum_spec_tools/docc.ast | 6555 +++++++++++++++++ coq/ethereum_spec_tools/docc.v | 43 + .../evm_tools/__init__.ast | 498 ++ coq/ethereum_spec_tools/evm_tools/__init__.v | 63 + .../evm_tools/__main__.ast | 24 + coq/ethereum_spec_tools/evm_tools/__main__.v | 3 + .../evm_tools/b11r/__init__.ast | 727 ++ .../evm_tools/b11r/__init__.v | 49 + .../evm_tools/b11r/b11r_types.ast | 1006 +++ .../evm_tools/b11r/b11r_types.v | 5 + coq/ethereum_spec_tools/evm_tools/daemon.ast | 897 +++ coq/ethereum_spec_tools/evm_tools/daemon.v | 22 + .../evm_tools/loaders/__init__.ast | 5 + .../evm_tools/loaders/__init__.v | 5 + .../evm_tools/loaders/fixture_loader.ast | 1203 +++ .../evm_tools/loaders/fixture_loader.v | 15 + .../evm_tools/loaders/fork_loader.ast | 1636 ++++ .../evm_tools/loaders/fork_loader.v | 5 + .../evm_tools/loaders/transaction_loader.ast | 1113 +++ .../evm_tools/loaders/transaction_loader.v | 12 + .../evm_tools/statetest/__init__.ast | 1515 ++++ .../evm_tools/statetest/__init__.v | 118 + .../evm_tools/t8n/__init__.ast | 3374 +++++++++ .../evm_tools/t8n/__init__.v | 64 + coq/ethereum_spec_tools/evm_tools/t8n/env.ast | 1480 ++++ coq/ethereum_spec_tools/evm_tools/t8n/env.v | 5 + .../evm_tools/t8n/evm_trace.ast | 1747 +++++ .../evm_tools/t8n/evm_trace.v | 61 + .../evm_tools/t8n/t8n_types.ast | 2378 ++++++ .../evm_tools/t8n/t8n_types.v | 5 + coq/ethereum_spec_tools/evm_tools/utils.ast | 934 +++ coq/ethereum_spec_tools/evm_tools/utils.v | 80 + coq/ethereum_spec_tools/forks.ast | 1430 ++++ coq/ethereum_spec_tools/forks.v | 8 + coq/ethereum_spec_tools/lint/__init__.ast | 870 +++ coq/ethereum_spec_tools/lint/__init__.v | 37 + coq/ethereum_spec_tools/lint/__main__.ast | 24 + coq/ethereum_spec_tools/lint/__main__.v | 8 + .../lint/lints/glacier_forks_hygiene.ast | 1253 ++++ .../lint/lints/glacier_forks_hygiene.v | 21 + .../lint/lints/import_hygiene.ast | 497 ++ .../lint/lints/import_hygiene.v | 8 + .../lint/lints/patch_hygiene.ast | 858 +++ .../lint/lints/patch_hygiene.v | 8 + coq/ethereum_spec_tools/new_fork.ast | 828 +++ coq/ethereum_spec_tools/new_fork.v | 57 + coq/ethereum_spec_tools/patch_tool.ast | 379 + coq/ethereum_spec_tools/patch_tool.v | 32 + coq/ethereum_spec_tools/sync.ast | 5912 +++++++++++++++ coq/ethereum_spec_tools/sync.v | 25 + coq/translate.py | 124 +- 728 files changed, 94869 insertions(+), 37285 deletions(-) create mode 100644 coq/ethereum_optimized/__init__.ast create mode 100644 coq/ethereum_optimized/__init__.v create mode 100644 coq/ethereum_optimized/fork.ast create mode 100644 coq/ethereum_optimized/fork.v create mode 100644 coq/ethereum_optimized/state_db.ast create mode 100644 coq/ethereum_optimized/state_db.v create mode 100644 coq/ethereum_optimized/utils.ast create mode 100644 coq/ethereum_optimized/utils.v create mode 100644 coq/ethereum_spec_tools/__init__.ast create mode 100644 coq/ethereum_spec_tools/__init__.v create mode 100644 coq/ethereum_spec_tools/docc.ast create mode 100644 coq/ethereum_spec_tools/docc.v create mode 100644 coq/ethereum_spec_tools/evm_tools/__init__.ast create mode 100644 coq/ethereum_spec_tools/evm_tools/__init__.v create mode 100644 coq/ethereum_spec_tools/evm_tools/__main__.ast create mode 100644 coq/ethereum_spec_tools/evm_tools/__main__.v create mode 100644 coq/ethereum_spec_tools/evm_tools/b11r/__init__.ast create mode 100644 coq/ethereum_spec_tools/evm_tools/b11r/__init__.v create mode 100644 coq/ethereum_spec_tools/evm_tools/b11r/b11r_types.ast create mode 100644 coq/ethereum_spec_tools/evm_tools/b11r/b11r_types.v create mode 100644 coq/ethereum_spec_tools/evm_tools/daemon.ast create mode 100644 coq/ethereum_spec_tools/evm_tools/daemon.v create mode 100644 coq/ethereum_spec_tools/evm_tools/loaders/__init__.ast create mode 100644 coq/ethereum_spec_tools/evm_tools/loaders/__init__.v create mode 100644 coq/ethereum_spec_tools/evm_tools/loaders/fixture_loader.ast create mode 100644 coq/ethereum_spec_tools/evm_tools/loaders/fixture_loader.v create mode 100644 coq/ethereum_spec_tools/evm_tools/loaders/fork_loader.ast create mode 100644 coq/ethereum_spec_tools/evm_tools/loaders/fork_loader.v create mode 100644 coq/ethereum_spec_tools/evm_tools/loaders/transaction_loader.ast create mode 100644 coq/ethereum_spec_tools/evm_tools/loaders/transaction_loader.v create mode 100644 coq/ethereum_spec_tools/evm_tools/statetest/__init__.ast create mode 100644 coq/ethereum_spec_tools/evm_tools/statetest/__init__.v create mode 100644 coq/ethereum_spec_tools/evm_tools/t8n/__init__.ast create mode 100644 coq/ethereum_spec_tools/evm_tools/t8n/__init__.v create mode 100644 coq/ethereum_spec_tools/evm_tools/t8n/env.ast create mode 100644 coq/ethereum_spec_tools/evm_tools/t8n/env.v create mode 100644 coq/ethereum_spec_tools/evm_tools/t8n/evm_trace.ast create mode 100644 coq/ethereum_spec_tools/evm_tools/t8n/evm_trace.v create mode 100644 coq/ethereum_spec_tools/evm_tools/t8n/t8n_types.ast create mode 100644 coq/ethereum_spec_tools/evm_tools/t8n/t8n_types.v create mode 100644 coq/ethereum_spec_tools/evm_tools/utils.ast create mode 100644 coq/ethereum_spec_tools/evm_tools/utils.v create mode 100644 coq/ethereum_spec_tools/forks.ast create mode 100644 coq/ethereum_spec_tools/forks.v create mode 100644 coq/ethereum_spec_tools/lint/__init__.ast create mode 100644 coq/ethereum_spec_tools/lint/__init__.v create mode 100644 coq/ethereum_spec_tools/lint/__main__.ast create mode 100644 coq/ethereum_spec_tools/lint/__main__.v create mode 100644 coq/ethereum_spec_tools/lint/lints/glacier_forks_hygiene.ast create mode 100644 coq/ethereum_spec_tools/lint/lints/glacier_forks_hygiene.v create mode 100644 coq/ethereum_spec_tools/lint/lints/import_hygiene.ast create mode 100644 coq/ethereum_spec_tools/lint/lints/import_hygiene.v create mode 100644 coq/ethereum_spec_tools/lint/lints/patch_hygiene.ast create mode 100644 coq/ethereum_spec_tools/lint/lints/patch_hygiene.v create mode 100644 coq/ethereum_spec_tools/new_fork.ast create mode 100644 coq/ethereum_spec_tools/new_fork.v create mode 100644 coq/ethereum_spec_tools/patch_tool.ast create mode 100644 coq/ethereum_spec_tools/patch_tool.v create mode 100644 coq/ethereum_spec_tools/sync.ast create mode 100644 coq/ethereum_spec_tools/sync.v diff --git a/coq/ethereum/__init__.v b/coq/ethereum/__init__.v index 66fc97f212..d5e3c1fcff 100644 --- a/coq/ethereum/__init__.v +++ b/coq/ethereum/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* ### Introduction diff --git a/coq/ethereum/arrow_glacier/__init__.v b/coq/ethereum/arrow_glacier/__init__.v index 46596e6954..4f971c997d 100644 --- a/coq/ethereum/arrow_glacier/__init__.v +++ b/coq/ethereum/arrow_glacier/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* The Arrow Glacier fork delays the difficulty bomb. There are no other changes in this fork. diff --git a/coq/ethereum/arrow_glacier/blocks.v b/coq/ethereum/arrow_glacier/blocks.v index 1132722431..1bb452d42a 100644 --- a/coq/ethereum/arrow_glacier/blocks.v +++ b/coq/ethereum/arrow_glacier/blocks.v @@ -1,3 +1,4 @@ +(* 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 @@ -14,6 +15,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. -Require arrow_glacier.fork_types. -Require arrow_glacier.transactions. +Require ethereum.crypto.hash. +Require ethereum.arrow_glacier.fork_types. +Require ethereum.arrow_glacier.transactions. diff --git a/coq/ethereum/arrow_glacier/bloom.v b/coq/ethereum/arrow_glacier/bloom.v index 8549854244..2183f9ba63 100644 --- a/coq/ethereum/arrow_glacier/bloom.v +++ b/coq/ethereum/arrow_glacier/bloom.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Logs Bloom ^^^^^^^^^^^^^^^^^^^ @@ -19,10 +20,10 @@ eliminating blocks and receipts from their search. Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require arrow_glacier.blocks. -Require arrow_glacier.fork_types. +Require ethereum.arrow_glacier.blocks. +Require ethereum.arrow_glacier.fork_types. -Definition add_to_bloom : M unit := +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := (* Add a bloom entry to the bloom filter (`bloom`). @@ -37,13 +38,15 @@ Definition add_to_bloom : M unit := bloom_entry : An entry which is to be added to bloom filter. *) - let* hash := ethereum.crypto.hash.keccak256 (| - bloom_entry - |) in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition logs_bloom : M unit := +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := (* Obtain the logs bloom from a list of log entries. @@ -63,4 +66,4 @@ Definition logs_bloom : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/exceptions.v b/coq/ethereum/arrow_glacier/exceptions.v index 137ea143f6..9a313f6d0e 100644 --- a/coq/ethereum/arrow_glacier/exceptions.v +++ b/coq/ethereum/arrow_glacier/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Exceptions specific to this fork. *) diff --git a/coq/ethereum/arrow_glacier/fork.v b/coq/ethereum/arrow_glacier/fork.v index aaced5b610..bb6c6a0dd8 100644 --- a/coq/ethereum/arrow_glacier/fork.v +++ b/coq/ethereum/arrow_glacier/fork.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^ @@ -20,16 +21,18 @@ Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.ethash. Require ethereum.exceptions. -Require arrow_glacier.blocks. -Require arrow_glacier.bloom. -Require arrow_glacier.fork_types. -Require arrow_glacier.state. -Require arrow_glacier.transactions. -Require arrow_glacier.trie. -Require arrow_glacier.utils.message. -Require arrow_glacier.vm.interpreter. - -Definition apply_fork : M unit := +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. @@ -49,9 +52,9 @@ Definition apply_fork : M unit := Upgraded block chain object for this hard fork. *) (* TODO statement *) + M.pure tt. - -Definition get_last_256_block_hashes : M unit := +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. @@ -71,22 +74,28 @@ Definition get_last_256_block_hashes : M unit := recent_block_hashes : `List[Hash32]` Hashes of the recent 256 blocks in order of increasing block number. *) - let* recent_blocks := (* TODO expression *) in - (* TODO statement *) - let* recent_block_hashes := (* TODO expression *) in - (* TODO statement *) - let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *).["header"] - |) - |) in - do* recent_block_hashes.["append"] (| - most_recent_block_hash - |) in - (* TODO statement *) - - -Definition state_transition : M unit := + 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. @@ -108,43 +117,47 @@ Definition state_transition : M unit := block : Block to apply to `chain`. *) - let* parent_header := (* TODO expression *).["header"] in - do* validate_header (| - block.["header"], - parent_header - |) in - do* validate_ommers (| - block.["ommers"], - block.["header"], + 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 - let* apply_body_output := apply_body (| - chain.["state"], - get_last_256_block_hashes (| - chain - |), - block.["header"].["coinbase"], - block.["header"].["number"], - block.["header"].["base_fee_per_gas"], - block.["header"].["gas_limit"], - block.["header"].["timestamp"], - block.["header"].["difficulty"], - block.["transactions"], - block.["ommers"], - chain.["chain_id"] - |) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - do* chain.["blocks"].["append"] (| + |) ]] 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 + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_base_fee_per_gas : M unit := +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. @@ -164,13 +177,15 @@ Definition calculate_base_fee_per_gas : M unit := base_fee_per_gas : `Uint` Base fee per gas for the block. *) - let* parent_gas_target := (* TODO expression *) in + do* M.assign "parent_gas_target" [[ + (* TODO expression *) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition validate_header : M unit := +Definition validate_header (header : Header) (parent_header : Header) : M unit := (* Verifies a block header. @@ -189,37 +204,45 @@ Definition validate_header : M unit := Parent Header of the header to check for correctness *) (* TODO statement *) - let* expected_base_fee_per_gas := calculate_base_fee_per_gas (| - header.["gas_limit"], - parent_header.["gas_limit"], - parent_header.["gas_used"], - parent_header.["base_fee_per_gas"] - |) in - (* TODO statement *) - let* parent_has_ommers := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* block_difficulty := calculate_block_difficulty (| - header.["number"], - header.["timestamp"], - parent_header.["timestamp"], - parent_header.["difficulty"], - parent_has_ommers - |) in - (* TODO statement *) - let* block_parent_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - parent_header - |) - |) in - (* TODO statement *) - do* validate_proof_of_work (| + 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 - + |) ]] in + M.pure tt. -Definition generate_header_hash_for_pow : M unit := +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. @@ -242,11 +265,13 @@ Definition generate_header_hash_for_pow : M unit := hash : `Hash32` The PoW valid rlp hash of the passed in header. *) - let* header_data_without_pow_artefacts := (* TODO expression *) in + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition validate_proof_of_work : M unit := +Definition validate_proof_of_work (header : Header) : M unit := (* Validates the Proof of Work constraints. @@ -261,19 +286,25 @@ Definition validate_proof_of_work : M unit := header : Header of interest. *) - let* header_hash := generate_header_hash_for_pow (| - header - |) in - let* cache := ethereum.ethash.generate_cache (| - header.["number"] - |) in + 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 *) - let* limit := (* TODO expression *) in + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition check_transaction : M unit := +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. @@ -301,15 +332,17 @@ Definition check_transaction : M unit := If the transaction is not includable. *) (* TODO statement *) - let* sender_address := recover_sender (| - chain_id, - tx - |) in + 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 : M unit := +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. @@ -330,13 +363,15 @@ Definition make_receipt : M unit := receipt : The receipt for the transaction. *) - let* receipt := blocks.Receipt (| + do* M.assign "receipt" [[ + blocks.Receipt ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition apply_body : M unit := +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. @@ -379,25 +414,31 @@ Definition apply_body : M unit := apply_body_output : `ApplyBodyOutput` Output of applying the block body to the state. *) - let* gas_available := block_gas_limit in + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - do* pay_rewards (| + do* [[ M.get_local ~(| "pay_rewards" |) ~(| state, block_number, coinbase, ommers - |) in - let* block_gas_used := (* TODO expression *) in - let* block_logs_bloom := bloom.logs_bloom (| - block_logs - |) in - (* TODO statement *) - - -Definition validate_ommers : M unit := + |) ]] 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. @@ -419,23 +460,31 @@ Definition validate_ommers : M unit := chain : History and current state. *) - let* block_hash := rlp.["rlp_hash"] (| - block_header - |) in + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* ommers_hashes := (* TODO expression *) in + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* recent_canonical_blocks := (* TODO expression *) in - let* recent_canonical_block_hashes := (* TODO expression *) in + 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 : M unit := +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. @@ -461,21 +510,25 @@ Definition pay_rewards : M unit := ommers : List of ommers mentioned in the current block. *) - let* ommer_count := ethereum_types.numeric.U256 (| - len (| - ommers - |) - |) in - let* miner_reward := (* TODO expression *) in - do* state.create_ether (| + 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, - miner_reward - |) in + M.get_local ~(| "miner_reward" |) + |) ]] in (* TODO statement *) + M.pure tt. - -Definition process_transaction : M unit := +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := (* Execute a transaction against the provided environment. @@ -503,74 +556,108 @@ Definition process_transaction : M unit := Logs generated during execution. *) (* TODO statement *) - let* sender := env.["origin"] in - let* sender_account := state.get_account (| - env.["state"], - sender - |) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* effective_gas_fee := (* TODO expression *) in - let* gas := (* TODO expression *) in - do* state.increment_nonce (| - env.["state"], - sender - |) in - let* sender_balance_after_gas_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - ethereum_types.numeric.U256 (| - sender_balance_after_gas_fee + 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 - let* preaccessed_addresses := set (| - - |) in - let* preaccessed_storage_keys := set (| - - |) in - (* TODO statement *) - let* message := utils.message.prepare_message (| - sender, - tx.["to"], - tx.["value"], - tx.["data"], - gas, - env - |) in - let* output := vm.interpreter.process_message_call (| - message, - env - |) in - let* gas_used := (* TODO expression *) in - let* gas_refund := min (| - (* TODO expression *), - ethereum_types.numeric.Uint (| - output.["refund_counter"] - |) - |) in - let* gas_refund_amount := (* TODO expression *) in - let* priority_fee_per_gas := (* TODO expression *) in - let* transaction_fee := (* TODO expression *) in - let* total_gas_used := (* TODO expression *) in - let* sender_balance_after_refund := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - sender_balance_after_refund - |) in - let* coinbase_balance_after_mining_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - - -Definition validate_transaction : M unit := + |) ]] 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. @@ -598,9 +685,9 @@ Definition validate_transaction : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition calculate_intrinsic_cost : M unit := +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := (* Calculates the gas that is charged before execution is started. @@ -623,15 +710,19 @@ Definition calculate_intrinsic_cost : M unit := verified : `ethereum.base_types.Uint` The intrinsic cost of the transaction. *) - let* data_cost := (* TODO expression *) in + do* M.assign "data_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) - let* access_list_cost := (* TODO expression *) in + do* M.assign "access_list_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition recover_sender : M unit := +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := (* Extracts the sender address from a transaction. @@ -658,9 +749,9 @@ Definition recover_sender : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_pre155 : M unit := +Definition signing_hash_pre155 (tx : LegacyTransaction) : M Hash32 := (* Compute the hash of a transaction used in a legacy (pre EIP 155) signature. @@ -675,9 +766,9 @@ Definition signing_hash_pre155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_155 : M unit := +Definition signing_hash_155 (tx : LegacyTransaction) (chain_id : U64) : M Hash32 := (* Compute the hash of a transaction used in a EIP 155 signature. @@ -694,9 +785,9 @@ Definition signing_hash_155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_2930 : M unit := +Definition signing_hash_2930 (tx : AccessListTransaction) : M Hash32 := (* Compute the hash of a transaction used in a EIP 2930 signature. @@ -711,9 +802,9 @@ Definition signing_hash_2930 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_1559 : M unit := +Definition signing_hash_1559 (tx : FeeMarketTransaction) : M Hash32 := (* Compute the hash of a transaction used in a EIP 1559 signature. @@ -728,9 +819,9 @@ Definition signing_hash_1559 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition compute_header_hash : M unit := +Definition compute_header_hash (header : Header) : M Hash32 := (* Computes the hash of a block header. @@ -763,9 +854,9 @@ Definition compute_header_hash : M unit := Hash of the header. *) (* TODO statement *) + M.pure tt. - -Definition check_gas_limit : M unit := +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := (* Validates the gas limit for a block. @@ -793,14 +884,16 @@ Definition check_gas_limit : M unit := check : `bool` True if gas limit constraints are satisfied, False otherwise. *) - let* max_adjustment_delta := (* TODO expression *) in + 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 : M unit := +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. @@ -839,9 +932,15 @@ Definition calculate_block_difficulty : M unit := difficulty : `ethereum.base_types.Uint` Computed difficulty for a block. *) - let* offset := (* TODO expression *) in - let* difficulty := (* TODO expression *) in - let* num_bomb_periods := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - + 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.v b/coq/ethereum/arrow_glacier/fork_types.v index 14de99d5e5..d84cffdf45 100644 --- a/coq/ethereum/arrow_glacier/fork_types.v +++ b/coq/ethereum/arrow_glacier/fork_types.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Types ^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. +Require ethereum.__init__. +Require ethereum.crypto.hash. -Definition encode_account : M unit := +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := (* Encode `Account` dataclass. @@ -26,4 +28,4 @@ Definition encode_account : M unit := encoded without providing a storage root. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/state.v b/coq/ethereum/arrow_glacier/state.v index 97d1bf908b..1cde4ff47c 100644 --- a/coq/ethereum/arrow_glacier/state.v +++ b/coq/ethereum/arrow_glacier/state.v @@ -1,3 +1,4 @@ +(* Generated *) (* State ^^^^^ @@ -22,10 +23,10 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require arrow_glacier.fork_types. -Require arrow_glacier.trie. +Require ethereum.arrow_glacier.fork_types. +Require ethereum.arrow_glacier.trie. -Definition close_state : M unit := +Definition close_state (state : State) : M unit := (* Free resources held by the state. Used by optimized implementations to release file descriptors. @@ -34,9 +35,9 @@ Definition close_state : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition begin_transaction : M unit := +Definition begin_transaction (state : State) : M unit := (* Start a state transaction. @@ -48,12 +49,12 @@ Definition begin_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition commit_transaction : M unit := +Definition commit_transaction (state : State) : M unit := (* Commit a state transaction. @@ -62,13 +63,13 @@ Definition commit_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["pop"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition rollback_transaction : M unit := +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. @@ -80,9 +81,9 @@ Definition rollback_transaction : M unit := *) (* TODO assignment *) (* TODO statement *) + M.pure tt. - -Definition get_account : M unit := +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. @@ -102,14 +103,16 @@ Definition get_account : M unit := account : `Account` Account at address. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition get_account_optional : M unit := +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. @@ -126,14 +129,16 @@ Definition get_account_optional : M unit := account : `Account` Account at address. *) - let* account := trie.trie_get (| - state.["_main_trie"], - address - |) in + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition set_account : M unit := +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()`). @@ -147,14 +152,14 @@ Definition set_account : M unit := account : `Account` Account to set at address. *) - do* trie.trie_set (| - state.["_main_trie"], + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), address, account - |) in + |) ]] in + M.pure tt. - -Definition destroy_account : M unit := +Definition destroy_account (state : State) (address : Address) : M unit := (* Completely remove the account at `address` and all of its storage. @@ -169,18 +174,18 @@ Definition destroy_account : M unit := address : `Address` Address of account to destroy. *) - do* destroy_storage (| + do* [[ M.get_local ~(| "destroy_storage" |) ~(| state, address - |) in - do* set_account (| + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - (* TODO expression *) - |) in + tt + |) ]] in + M.pure tt. - -Definition destroy_storage : M unit := +Definition destroy_storage (state : State) (address : Address) : M unit := (* Completely remove the storage at `address`. @@ -192,9 +197,9 @@ Definition destroy_storage : M unit := Address of account whose storage is to be deleted. *) (* TODO statement *) + M.pure tt. - -Definition mark_account_created : M unit := +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 @@ -211,12 +216,12 @@ Definition mark_account_created : M unit := address : `Address` Address of the account that has been created. *) - do* state.["created_accounts"].["add"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| address - |) in - + |) ]] in + M.pure tt. -Definition get_storage : M unit := +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. @@ -235,19 +240,23 @@ Definition get_storage : M unit := value : `U256` Value at the key. *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition set_storage : M unit := +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. @@ -264,19 +273,21 @@ Definition set_storage : M unit := Value to set at the key. *) (* TODO statement *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - do* trie.trie_set (| - trie, + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), key, value - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition storage_root : M unit := +Definition storage_root (state : State) (address : Address) : M Root := (* Calculate the storage root of an account. @@ -294,9 +305,9 @@ Definition storage_root : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition state_root : M unit := +Definition state_root (state : State) : M Root := (* Calculate the state root. @@ -313,9 +324,9 @@ Definition state_root : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition account_exists : M unit := +Definition account_exists (state : State) (address : Address) : M bool := (* Checks if an account exists in the state trie @@ -332,9 +343,9 @@ Definition account_exists : M unit := True if account exists in the state trie, False otherwise *) (* TODO statement *) + M.pure tt. - -Definition account_has_code_or_nonce : M unit := +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := (* Checks if an account has non zero nonce or non empty code @@ -351,14 +362,16 @@ Definition account_has_code_or_nonce : M unit := True if if an account has non zero nonce or non empty code, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_empty : M unit := +Definition is_account_empty (state : State) (address : Address) : M bool := (* Checks if an account has zero nonce, empty code and zero balance. @@ -375,14 +388,16 @@ Definition is_account_empty : M unit := True if if an account has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition account_exists_and_is_empty : M unit := +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. @@ -400,14 +415,16 @@ Definition account_exists_and_is_empty : M unit := True if an account exists and has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_alive : M unit := +Definition is_account_alive (state : State) (address : Address) : M bool := (* Check whether is an account is both in the state and non empty. @@ -423,49 +440,51 @@ Definition is_account_alive : M unit := is_alive : `bool` True if the account is alive. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition modify_state : M unit := +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := (* Modify an `Account` in the `State`. *) - do* set_account (| + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - ethereum_types.frozen.modify (| - get_account (| + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| state, address |), f |) - |) in - + |) ]] in + M.pure tt. -Definition move_ether : M unit := +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := (* Move funds between accounts. *) (* TODO statement *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, sender_address, - reduce_sender_balance - |) in - do* modify_state (| + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| state, recipient_address, - increase_recipient_balance - |) in - + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. -Definition set_account_balance : M unit := +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := (* Sets the balance of an account. @@ -481,14 +500,14 @@ Definition set_account_balance : M unit := The amount that needs to set in balance. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - set_balance - |) in + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. - -Definition touch_account : M unit := +Definition touch_account (state : State) (address : Address) : M unit := (* Initializes an account to state. @@ -501,9 +520,9 @@ Definition touch_account : M unit := The address of the account that need to initialised. *) (* TODO statement *) + M.pure tt. - -Definition increment_nonce : M unit := +Definition increment_nonce (state : State) (address : Address) : M unit := (* Increments the nonce of an account. @@ -516,14 +535,14 @@ Definition increment_nonce : M unit := Address of the account whose nonce needs to be incremented. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_nonce - |) in + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. - -Definition set_code : M unit := +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := (* Sets Account code. @@ -539,14 +558,14 @@ Definition set_code : M unit := The bytecode that needs to be set. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - write_code - |) in - + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. -Definition create_ether : M unit := +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := (* Add newly created ether to an account. @@ -560,14 +579,14 @@ Definition create_ether : M unit := The amount of ether to be added to the account of interest. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_balance - |) in - + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. -Definition get_storage_original : M unit := +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 @@ -584,10 +603,12 @@ Definition get_storage_original : M unit := *) (* TODO statement *) (* TODO assignment *) - let* original_account_trie := original_trie.["get"] (| - address - |) in + 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.v b/coq/ethereum/arrow_glacier/transactions.v index f270c148f2..2d3c2e5941 100644 --- a/coq/ethereum/arrow_glacier/transactions.v +++ b/coq/ethereum/arrow_glacier/transactions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, @@ -9,19 +10,20 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require arrow_glacier.exceptions. -Require arrow_glacier.fork_types. +Require ethereum.__init__. +Require ethereum.arrow_glacier.exceptions. +Require ethereum.arrow_glacier.fork_types. -Definition encode_transaction : M unit := +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 : M unit := +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.v b/coq/ethereum/arrow_glacier/trie.v index 548de91e1c..6b8953f256 100644 --- a/coq/ethereum/arrow_glacier/trie.v +++ b/coq/ethereum/arrow_glacier/trie.v @@ -1,3 +1,4 @@ +(* Generated *) (* State Trie ^^^^^^^^^^ @@ -14,7 +15,7 @@ The state trie is the structure responsible for storing *) -Definition encode_internal_node : M unit := +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 @@ -35,22 +36,24 @@ Definition encode_internal_node : M unit := *) (* TODO statement *) (* TODO statement *) - let* encoded := rlp.["encode"] (| - unencoded - |) in + 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 : M unit := +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 : M unit := +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. @@ -66,9 +69,9 @@ Definition copy_trie : M unit := A copy of the trie. *) (* TODO statement *) + M.pure tt. - -Definition trie_set : M unit := +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := (* Stores an item in a Merkle Trie. @@ -85,9 +88,9 @@ Definition trie_set : M unit := Node to insert at `key`. *) (* TODO statement *) + M.pure tt. - -Definition trie_get : M unit := +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := (* Gets an item from the Merkle Trie. @@ -106,17 +109,17 @@ Definition trie_get : M unit := Node at `key` in the trie. *) (* TODO statement *) + M.pure tt. - -Definition common_prefix_length : M unit := +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 : M unit := +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := (* Compresses nibble-list into a standard byte array with a flag. @@ -150,14 +153,16 @@ Definition nibble_list_to_compact : M unit := compressed : `bytearray` Compact byte array. *) - let* compact := bytearray (| + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition bytes_to_nibble_list : M unit := +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := (* Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). @@ -171,14 +176,16 @@ Definition bytes_to_nibble_list : M unit := nibble_list : `Bytes` The `Bytes` in nibble-list format. *) - let* nibble_list := bytearray (| - (* TODO expression *) - |) in + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _prepare_trie : M unit := +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. @@ -199,9 +206,9 @@ Definition _prepare_trie : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition root : M unit := +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := (* Computes the root of a modified merkle patricia trie (MPT). @@ -219,22 +226,26 @@ Definition root : M unit := root : `.fork_types.Root` MPT root of the underlying key-value pairs. *) - let* obj := _prepare_trie (| - trie, - get_storage_root - |) in - let* root_node := encode_internal_node (| - patricialize (| - obj, - Uint (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) + M.pure tt. - -Definition patricialize : M unit := +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := (* Structural composition function. @@ -254,21 +265,29 @@ Definition patricialize : M unit := Root node of `obj`. *) (* TODO statement *) - let* arbitrary_key := next (| - iter (| - obj - |) - |) in + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in (* TODO statement *) - let* substring := (* TODO expression *) in - let* prefix_length := len (| - substring - |) in + 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 *) - let* value := (* TODO expression *) in + do* M.assign "value" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/utils/__init__.v b/coq/ethereum/arrow_glacier/utils/__init__.v index beff4482b1..7f30fe939b 100644 --- a/coq/ethereum/arrow_glacier/utils/__init__.v +++ b/coq/ethereum/arrow_glacier/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions unique to this particular fork. *) diff --git a/coq/ethereum/arrow_glacier/utils/address.v b/coq/ethereum/arrow_glacier/utils/address.v index 08514e27df..4fc0d539ed 100644 --- a/coq/ethereum/arrow_glacier/utils/address.v +++ b/coq/ethereum/arrow_glacier/utils/address.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,9 +19,10 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require arrow_glacier.fork_types. +Require ethereum.__init__. +Require ethereum.arrow_glacier.fork_types. -Definition to_address : M unit := +Definition to_address (data : (* TODO type *)) : M Address := (* Convert a Uint or U256 value to a valid address (20 bytes). @@ -35,9 +37,9 @@ Definition to_address : M unit := The obtained address. *) (* TODO statement *) + M.pure tt. - -Definition compute_contract_address : M unit := +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := (* Computes address of the new account that needs to be created. @@ -54,20 +56,26 @@ Definition compute_contract_address : M unit := address: `Address` The computed address of the new account. *) - let* computed_address := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *) - |) - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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 : M unit := +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. @@ -86,14 +94,22 @@ Definition compute_create2_contract_address : M unit := address: `ethereum.arrow_glacier.fork_types.Address` The computed address of the new account. *) - let* preimage := (* TODO expression *) in - let* computed_address := ethereum.crypto.hash.keccak256 (| - preimage - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/arrow_glacier/utils/hexadecimal.v index 1ac7f475c4..ea593a7f88 100644 --- a/coq/ethereum/arrow_glacier/utils/hexadecimal.v +++ b/coq/ethereum/arrow_glacier/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Arrow Glacier types. *) Require ethereum.utils.hexadecimal. -Require arrow_glacier.fork_types. +Require ethereum.arrow_glacier.fork_types. -Definition hex_to_root : M unit := +Definition hex_to_root (hex_string : str) : M Root := (* Convert hex string to trie root. @@ -31,9 +32,9 @@ Definition hex_to_root : M unit := Trie root obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bloom : M unit := +Definition hex_to_bloom (hex_string : str) : M Bloom := (* Convert hex string to bloom. @@ -48,9 +49,9 @@ Definition hex_to_bloom : M unit := Bloom obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_address : M unit := +Definition hex_to_address (hex_string : str) : M Address := (* Convert hex string to Address (20 bytes). @@ -65,4 +66,4 @@ Definition hex_to_address : M unit := The address obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/utils/message.v b/coq/ethereum/arrow_glacier/utils/message.v index 44807f2118..46eb905f41 100644 --- a/coq/ethereum/arrow_glacier/utils/message.v +++ b/coq/ethereum/arrow_glacier/utils/message.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For The Message Data-structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,13 +17,13 @@ specification. Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require arrow_glacier.fork_types. -Require arrow_glacier.state. -Require arrow_glacier.vm. -Require arrow_glacier.vm.precompiled_contracts.mapping. -Require arrow_glacier.utils.address. +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 : M unit := +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. @@ -61,22 +62,24 @@ Definition prepare_message : M unit := Items containing contract creation or message call specific data. *) (* TODO statement *) - let* accessed_addresses := set (| + do* M.assign "accessed_addresses" [[ + M.get_local ~(| "set" |) ~(| - |) in - do* accessed_addresses.["add"] (| - current_target - |) in - do* accessed_addresses.["add"] (| + |) 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* accessed_addresses.["update"] (| - vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS.["keys"] (| + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS, "keys" |) ~(| |) - |) in - do* accessed_addresses.["update"] (| + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| preaccessed_addresses - |) in + |) ]] in (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/__init__.v b/coq/ethereum/arrow_glacier/vm/__init__.v index 4275b0cf57..c9ac2fbb9d 100644 --- a/coq/ethereum/arrow_glacier/vm/__init__.v +++ b/coq/ethereum/arrow_glacier/vm/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,12 +19,12 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require arrow_glacier.blocks. -Require arrow_glacier.fork_types. -Require arrow_glacier.state. -Require arrow_glacier.vm.precompiled_contracts. +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 : M unit := +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of a successful `child_evm` into the parent `evm`. @@ -34,25 +35,31 @@ Definition incorporate_child_on_success : M unit := 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 *) - (* TODO statement *) - (* TODO statement *) - do* evm.["accounts_to_delete"].["update"] (| - child_evm.["accounts_to_delete"] - |) in - do* evm.["touched_accounts"].["update"] (| - child_evm.["touched_accounts"] - |) in - (* TODO statement *) - do* evm.["accessed_addresses"].["update"] (| - child_evm.["accessed_addresses"] - |) in - do* evm.["accessed_storage_keys"].["update"] (| - child_evm.["accessed_storage_keys"] - |) in + 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 : M unit := +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. @@ -65,5 +72,7 @@ Definition incorporate_child_on_error : M unit := *) (* TODO statement *) (* 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.v b/coq/ethereum/arrow_glacier/vm/exceptions.v index 1784494410..47e26555d5 100644 --- a/coq/ethereum/arrow_glacier/vm/exceptions.v +++ b/coq/ethereum/arrow_glacier/vm/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Exceptions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/arrow_glacier/vm/gas.v b/coq/ethereum/arrow_glacier/vm/gas.v index 2c6dcc12e1..5038c7bae4 100644 --- a/coq/ethereum/arrow_glacier/vm/gas.v +++ b/coq/ethereum/arrow_glacier/vm/gas.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Gas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,9 +18,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.trace. Require ethereum.utils.numeric. -Require arrow_glacier.vm.exceptions. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.exceptions. -Definition charge_gas : M unit := +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := (* Subtracts `amount` from `evm.gas_left`. @@ -31,18 +33,18 @@ Definition charge_gas : M unit := The amount of gas the current operation requires. *) - do* ethereum.trace.evm_trace (| + do* [[ ethereum.trace.evm_trace ~(| evm, - ethereum.trace.GasAndRefund (| - int (| + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| amount |) |) - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_memory_gas_cost : M unit := +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, @@ -58,14 +60,22 @@ Definition calculate_memory_gas_cost : M unit := total_gas_cost : `ethereum.base_types.Uint` The gas cost for storing data in memory. *) - let* size_in_words := (* TODO expression *) in - let* linear_cost := (* TODO expression *) in - let* quadratic_cost := (* TODO expression *) in - let* total_gas_cost := (* TODO expression *) in + 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 : M unit := +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := (* Calculates the gas amount to extend memory @@ -81,22 +91,28 @@ Definition calculate_gas_extend_memory : M unit := ------- extend_memory: `ExtendMemory` *) - let* size_to_extend := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* to_be_paid := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* current_size := ethereum_types.numeric.Uint (| - len (| - memory - |) - |) in + 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 : M unit := +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. @@ -122,18 +138,22 @@ Definition calculate_message_call_gas : M unit := ------- message_call_gas: `MessageCallGas` *) - let* call_stipend := (* TODO expression *) in + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* gas := min (| - gas, - max_message_call_gas (| - (* TODO expression *) - |) - |) in + 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 : M unit := +Definition max_message_call_gas (gas : Uint) : M Uint := (* Calculates the maximum gas that is allowed for making a message call @@ -148,4 +168,4 @@ Definition max_message_call_gas : M unit := The maximum gas allowed for making the message-call. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/instructions/__init__.v b/coq/ethereum/arrow_glacier/vm/instructions/__init__.v index b36b1ebfef..cbd7e7e63a 100644 --- a/coq/ethereum/arrow_glacier/vm/instructions/__init__.v +++ b/coq/ethereum/arrow_glacier/vm/instructions/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* EVM Instruction Encoding (Opcodes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/arrow_glacier/vm/instructions/arithmetic.v b/coq/ethereum/arrow_glacier/vm/instructions/arithmetic.v index 44588d8277..26812429f1 100644 --- a/coq/ethereum/arrow_glacier/vm/instructions/arithmetic.v +++ b/coq/ethereum/arrow_glacier/vm/instructions/arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,11 @@ Implementations of the EVM Arithmetic instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require arrow_glacier.vm.gas. -Require arrow_glacier.vm.stack. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.stack. -Definition add : M unit := +Definition add (evm : Evm) : M unit := (* Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -28,27 +30,37 @@ Definition add : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_add"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sub (evm : Evm) : M unit := (* Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -59,27 +71,37 @@ Definition sub : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_sub"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mul (evm : Evm) : M unit := (* Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -90,27 +112,37 @@ Definition mul : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_mul"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition div (evm : Evm) : M unit := (* Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -121,25 +153,33 @@ Definition div : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |) in - let* divisor := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - quotient - |) 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 : M unit := +Definition sdiv (evm : Evm) : M unit := (* Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -150,31 +190,39 @@ Definition sdiv : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* divisor := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - quotient + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mod : M unit := +Definition mod (evm : Evm) : M unit := (* Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -185,25 +233,33 @@ Definition mod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - remainder - |) in + |) ]] 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 : M unit := +Definition smod (evm : Evm) : M unit := (* Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -214,31 +270,39 @@ Definition smod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* y := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - remainder + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition addmod : M unit := +Definition addmod (evm : Evm) : M unit := (* Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -249,34 +313,44 @@ Definition addmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +Definition mulmod (evm : Evm) : M unit := (* Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -287,34 +361,44 @@ Definition mulmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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 : M unit := +Definition exp (evm : Evm) : M unit := (* Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -325,39 +409,53 @@ Definition exp : M unit := The current EVM frame. *) - let* base := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent_bits := exponent.["bit_length"] (| - - |) in - let* exponent_bytes := (* TODO expression *) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - pow (| - base, - exponent, - (* 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 - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition signextend : M unit := +Definition signextend (evm : Evm) : M unit := (* Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -368,20 +466,28 @@ Definition signextend : M unit := The current EVM frame. *) - let* byte_num := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/arrow_glacier/vm/instructions/bitwise.v index c95b791002..c5088ce92a 100644 --- a/coq/ethereum/arrow_glacier/vm/instructions/bitwise.v +++ b/coq/ethereum/arrow_glacier/vm/instructions/bitwise.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Bitwise Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM bitwise instructions. *) Require ethereum_types.numeric. -Require arrow_glacier.vm.gas. -Require arrow_glacier.vm.stack. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.stack. -Definition bitwise_and : M unit := +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. @@ -27,24 +29,32 @@ Definition bitwise_and : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_or : M unit := +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. @@ -55,24 +65,32 @@ Definition bitwise_or : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_xor : M unit := +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. @@ -83,24 +101,32 @@ Definition bitwise_xor : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_not : M unit := +Definition bitwise_not (evm : Evm) : M unit := (* Bitwise NOT operation of the top element of the stack. Pushes the result back on the stack. @@ -111,21 +137,27 @@ Definition bitwise_not : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition get_byte : M unit := +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 @@ -137,25 +169,33 @@ Definition get_byte : M unit := The current EVM frame. *) - let* byte_index := stack.pop (| - evm.["stack"] - |) in - let* word := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -164,29 +204,37 @@ Definition bitwise_shl : M unit := evm : The current EVM frame. *) - let* shift := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -195,25 +243,33 @@ Definition bitwise_shr : M unit := evm : The current EVM frame. *) - let* shift := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -222,24 +278,32 @@ Definition bitwise_sar : M unit := evm : The current EVM frame. *) - let* shift := int (| - stack.pop (| - evm.["stack"] - |) - |) in - let* signed_value := stack.pop (| - evm.["stack"] - |).["to_signed"] (| + 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 - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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.v b/coq/ethereum/arrow_glacier/vm/instructions/block.v index 07dafe617e..4fc1907bac 100644 --- a/coq/ethereum/arrow_glacier/vm/instructions/block.v +++ b/coq/ethereum/arrow_glacier/vm/instructions/block.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Block Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM block instructions. *) Require ethereum_types.numeric. -Require arrow_glacier.vm.gas. -Require arrow_glacier.vm.stack. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.stack. -Definition block_hash : M unit := +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. @@ -27,27 +29,35 @@ Definition block_hash : M unit := The current EVM frame. *) - let* block_number := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* max_block_number := (* TODO expression *) in + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition coinbase : M unit := +Definition coinbase (evm : Evm) : M unit := (* Push the current block's beneficiary address (address of the block miner) onto the stack. @@ -62,20 +72,24 @@ Definition coinbase : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["coinbase"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition timestamp : M unit := +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. @@ -90,18 +104,22 @@ Definition timestamp : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["env"].["time"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition number (evm : Evm) : M unit := (* Push the current block's number onto the stack. @@ -115,20 +133,24 @@ Definition number : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["number"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition difficulty : M unit := +Definition difficulty (evm : Evm) : M unit := (* Push the current block's difficulty onto the stack. @@ -142,20 +164,24 @@ Definition difficulty : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["difficulty"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_limit : M unit := +Definition gas_limit (evm : Evm) : M unit := (* Push the current block's gas limit onto the stack. @@ -169,20 +195,24 @@ Definition gas_limit : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_limit"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition chain_id : M unit := +Definition chain_id (evm : Evm) : M unit := (* Push the chain id onto the stack. @@ -193,15 +223,19 @@ Definition chain_id : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["chain_id"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/arrow_glacier/vm/instructions/comparison.v index e7f58b64d4..0e05bb361b 100644 --- a/coq/ethereum/arrow_glacier/vm/instructions/comparison.v +++ b/coq/ethereum/arrow_glacier/vm/instructions/comparison.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Comparison Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM Comparison instructions. *) Require ethereum_types.numeric. -Require arrow_glacier.vm.gas. -Require arrow_glacier.vm.stack. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.stack. -Definition less_than : M unit := +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. @@ -27,27 +29,37 @@ Definition less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_less_than : M unit := + |) ]] 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. @@ -57,31 +69,41 @@ Definition signed_less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition greater_than : M unit := + |) ]] 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. @@ -92,27 +114,37 @@ Definition greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_greater_than : M unit := + |) ]] 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. @@ -122,31 +154,41 @@ Definition signed_greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition equal : M unit := + |) ]] 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. @@ -157,27 +199,37 @@ Definition equal : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition is_zero : M unit := + |) ]] 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. @@ -188,19 +240,27 @@ Definition is_zero : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/arrow_glacier/vm/instructions/control_flow.v index 30741eb3aa..17c2e4cf05 100644 --- a/coq/ethereum/arrow_glacier/vm/instructions/control_flow.v +++ b/coq/ethereum/arrow_glacier/vm/instructions/control_flow.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Control Flow Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM control flow instructions. *) Require ethereum_types.numeric. -Require arrow_glacier.vm.gas. -Require arrow_glacier.vm.exceptions. -Require arrow_glacier.vm.stack. +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 : M unit := +Definition stop (evm : Evm) : M unit := (* Stop further execution of EVM code. @@ -29,10 +31,14 @@ Definition stop : M unit := (* TODO statement *) (* TODO statement *) (* TODO assignment *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jump : M unit := +Definition jump (evm : Evm) : M unit := (* Alter the program counter to the location specified by the top of the stack. @@ -43,20 +49,22 @@ Definition jump : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition jumpi : M unit := +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 @@ -68,23 +76,27 @@ Definition jumpi : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* conditional_value := stack.pop (| - evm.["stack"] - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition pc : M unit := +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. @@ -96,20 +108,24 @@ Definition pc : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["pc"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_left : M unit := +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. @@ -121,20 +137,24 @@ Definition gas_left : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["gas_left"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jumpdest : M unit := +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 @@ -147,10 +167,14 @@ Definition jumpdest : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_JUMPDEST - |) in - (* TODO statement *) + |) ]] 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.v b/coq/ethereum/arrow_glacier/vm/instructions/environment.v index 005e9ec07f..fc896dbe4a 100644 --- a/coq/ethereum/arrow_glacier/vm/instructions/environment.v +++ b/coq/ethereum/arrow_glacier/vm/instructions/environment.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,15 +16,16 @@ Implementations of the EVM environment related instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require arrow_glacier.fork_types. -Require arrow_glacier.state. -Require arrow_glacier.utils.address. -Require arrow_glacier.vm.memory. -Require arrow_glacier.vm.exceptions. -Require arrow_glacier.vm.gas. -Require arrow_glacier.vm.stack. - -Definition address : M unit := +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. @@ -34,20 +36,24 @@ Definition address : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["current_target"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition balance : M unit := +Definition balance (evm : Evm) : M unit := (* Pushes the balance of the given account onto the stack. @@ -57,24 +63,32 @@ Definition balance : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] + 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 - (* TODO statement *) - let* balance := state.get_account (| - evm.["env"].["state"], - address - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition origin : M unit := +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. @@ -86,20 +100,24 @@ Definition origin : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["origin"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition caller : M unit := +Definition caller (evm : Evm) : M unit := (* Pushes the address of the caller onto the stack. @@ -110,20 +128,24 @@ Definition caller : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["caller"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition callvalue : M unit := +Definition callvalue (evm : Evm) : M unit := (* Push the value (in wei) sent with the call onto the stack. @@ -134,18 +156,22 @@ Definition callvalue : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["message"].["value"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition calldataload (evm : Evm) : M unit := (* Push a word (32 bytes) of the input data belonging to the current environment onto the stack. @@ -156,30 +182,38 @@ Definition calldataload : M unit := The current EVM frame. *) - let* start_index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - start_index, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] 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* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - value + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 |) - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition calldatasize : M unit := +Definition calldatasize (evm : Evm) : M unit := (* Push the size of input data in current environment onto the stack. @@ -190,22 +224,26 @@ Definition calldatasize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["message"].["data"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition calldatacopy : M unit := +Definition calldatacopy (evm : Evm) : M unit := (* Copy a portion of the input data in current environment to memory. @@ -218,40 +256,60 @@ Definition calldatacopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* data_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - data_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition codesize (evm : Evm) : M unit := (* Push the size of code running in current environment onto the stack. @@ -262,22 +320,26 @@ Definition codesize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["code"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition codecopy : M unit := +Definition codecopy (evm : Evm) : M unit := (* Copy a portion of the code in current environment to memory. @@ -290,40 +352,60 @@ Definition codecopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["code"], - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition gasprice (evm : Evm) : M unit := (* Push the gas price used in current environment onto the stack. @@ -334,20 +416,24 @@ Definition gasprice : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_price"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition extcodesize : M unit := +Definition extcodesize (evm : Evm) : M unit := (* Push the code size of a given account onto the stack. @@ -357,28 +443,36 @@ Definition extcodesize : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - (* TODO statement *) - let* codesize := ethereum_types.numeric.U256 (| - len (| - state.get_account (| - evm.["env"].["state"], - address - |).["code"] + 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 - do* stack.push (| - evm.["stack"], - codesize - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition extcodecopy : M unit := +Definition extcodecopy (evm : Evm) : M unit := (* Copy a portion of an account's code to memory. @@ -388,46 +482,70 @@ Definition extcodecopy : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - (* TODO statement *) - let* code := state.get_account (| - evm.["env"].["state"], - address - |).["code"] in - let* value := vm.memory.buffer_read (| - code, - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in + 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 : M unit := +Definition returndatasize (evm : Evm) : M unit := (* Pushes the size of the return data buffer onto the stack. @@ -437,22 +555,26 @@ Definition returndatasize : M unit := The current EVM frame. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["return_data"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition returndatacopy : M unit := +Definition returndatacopy (evm : Evm) : M unit := (* Copies data from the return data buffer code to memory @@ -461,37 +583,57 @@ Definition returndatacopy : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* return_data_start_position := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - (* TODO statement *) - let* value := (* TODO expression *) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in + |) ]] 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 : M unit := +Definition extcodehash (evm : Evm) : M unit := (* Returns the keccak256 hash of a contract’s bytecode Parameters @@ -499,25 +641,33 @@ Definition extcodehash : M unit := evm : The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] + 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 - (* TODO statement *) - let* account := state.get_account (| - evm.["env"].["state"], - address - |) in - (* TODO statement *) - do* stack.push (| - evm.["stack"], - codehash - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition self_balance : M unit := +Definition self_balance (evm : Evm) : M unit := (* Pushes the balance of the current address to the stack. @@ -528,22 +678,28 @@ Definition self_balance : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_FAST_STEP - |) in - let* balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition base_fee (evm : Evm) : M unit := (* Pushes the base fee of the current block on to the stack. @@ -554,15 +710,19 @@ Definition base_fee : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["base_fee_per_gas"] + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/arrow_glacier/vm/instructions/keccak.v index e0f701b3b3..af472a7dc1 100644 --- a/coq/ethereum/arrow_glacier/vm/instructions/keccak.v +++ b/coq/ethereum/arrow_glacier/vm/instructions/keccak.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Keccak Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM keccak instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require arrow_glacier.vm.gas. -Require arrow_glacier.vm.memory. -Require arrow_glacier.vm.stack. +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 : M unit := +Definition keccak (evm : Evm) : M unit := (* Pushes to the stack the Keccak-256 hash of a region of memory. @@ -32,36 +34,56 @@ Definition keccak : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* word_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in - let* hash := ethereum.crypto.hash.keccak256 (| - data - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/arrow_glacier/vm/instructions/log.v index cba7bd19e9..65b0c921c8 100644 --- a/coq/ethereum/arrow_glacier/vm/instructions/log.v +++ b/coq/ethereum/arrow_glacier/vm/instructions/log.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Logging Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,13 +15,14 @@ Implementations of the EVM logging instructions. Require functools. Require ethereum_types.numeric. -Require arrow_glacier.blocks. -Require arrow_glacier.vm.exceptions. -Require arrow_glacier.vm.gas. -Require arrow_glacier.vm.memory. -Require arrow_glacier.vm.stack. +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 : M unit := +Definition log_n (evm : Evm) (num_topics : U256) : M unit := (* Appends a log entry, having `num_topics` topics, to the evm logs. @@ -35,27 +37,43 @@ Definition log_n : M unit := The number of topics to be included in the log entry. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* topics := (* TODO expression *) in + 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 *) - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in (* TODO statement *) - let* log_entry := blocks.Log (| + do* M.assign "log_entry" [[ + blocks.Log ~(| - |) in + |) in + ]] in (* TODO assignment *) - (* 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/memory.v b/coq/ethereum/arrow_glacier/vm/instructions/memory.v index 7dfeefbd5a..9cc059ed5b 100644 --- a/coq/ethereum/arrow_glacier/vm/instructions/memory.v +++ b/coq/ethereum/arrow_glacier/vm/instructions/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM Memory instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require arrow_glacier.vm.gas. -Require arrow_glacier.vm.memory. -Require arrow_glacier.vm.stack. +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 : M unit := +Definition mstore (evm : Evm) : M unit := (* Stores a word to memory. This also expands the memory, if the memory is @@ -30,32 +32,44 @@ Definition mstore : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* memory.memory_write (| - evm.["memory"], - start_position, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mstore8 (evm : Evm) : M unit := (* Stores a byte to memory. This also expands the memory, if the memory is @@ -67,33 +81,47 @@ Definition mstore8 : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ (* TODO expression *) - |) in - do* memory.memory_write (| - evm.["memory"], - start_position, - normalized_bytes_value - |) in - (* TODO statement *) - + ]] 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 : M unit := +Definition mload (evm : Evm) : M unit := (* Load word from memory. @@ -103,35 +131,47 @@ Definition mload : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.memory_read_bytes (| - evm.["memory"], - start_position, - ethereum_types.numeric.U256 (| - (* 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 - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition msize : M unit := +Definition msize (evm : Evm) : M unit := (* Push the size of active memory in bytes onto the stack. @@ -142,17 +182,21 @@ Definition msize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["memory"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/arrow_glacier/vm/instructions/stack.v index e2e7b545a9..201a93d910 100644 --- a/coq/ethereum/arrow_glacier/vm/instructions/stack.v +++ b/coq/ethereum/arrow_glacier/vm/instructions/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM stack related instructions. Require functools. Require ethereum_types.numeric. -Require arrow_glacier.vm.exceptions. -Require arrow_glacier.vm.gas. -Require 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.memory. -Definition pop : M unit := +Definition pop (evm : Evm) : M unit := (* Remove item from stack. @@ -28,18 +30,22 @@ Definition pop : M unit := The current EVM frame. *) - do* stack.["pop"] (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in + |) ]] in (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition push_n : M unit := +Definition push_n (evm : Evm) (num_bytes : int) : M unit := (* Pushes a N-byte immediate onto the stack. @@ -54,29 +60,33 @@ Definition push_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - evm.["code"], - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - num_bytes + |) ]] 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 - do* stack.["push"] (| - evm.["stack"], - data_to_push - |) in - (* TODO statement *) - - -Definition dup_n : M unit := + |) 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. @@ -91,20 +101,26 @@ Definition dup_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - let* data_to_duplicate := (* TODO expression *) in - do* stack.["push"] (| - evm.["stack"], - data_to_duplicate - |) 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 : M unit := +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. @@ -123,11 +139,15 @@ Definition swap_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - (* 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/storage.v b/coq/ethereum/arrow_glacier/vm/instructions/storage.v index fe286beabf..b1054ff0ff 100644 --- a/coq/ethereum/arrow_glacier/vm/instructions/storage.v +++ b/coq/ethereum/arrow_glacier/vm/instructions/storage.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Storage Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,12 +14,13 @@ Implementations of the EVM storage related instructions. *) Require ethereum_types.numeric. -Require arrow_glacier.state. -Require arrow_glacier.vm.exceptions. -Require arrow_glacier.vm.gas. -Require arrow_glacier.vm.stack. +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 : M unit := +Definition sload (evm : Evm) : M unit := (* Loads to the stack, the value corresponding to a certain key from the storage of the current account. @@ -29,25 +31,33 @@ Definition sload : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in + |) in + ]] in (* TODO statement *) - let* value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) 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 : M unit := +Definition sstore (evm : Evm) : M unit := (* Stores a value at a certain key in the current context's storage. @@ -57,41 +67,55 @@ Definition sstore : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in (* TODO statement *) - let* original_value := state.get_storage_original (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - let* current_value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - let* gas_cost := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in + M.get_local ~(| "gas_cost" |) + |) ]] in (* TODO statement *) - do* state.set_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key, - new_value - |) 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.v b/coq/ethereum/arrow_glacier/vm/instructions/system.v index 6ea0d1e6bc..d00e517b01 100644 --- a/coq/ethereum/arrow_glacier/vm/instructions/system.v +++ b/coq/ethereum/arrow_glacier/vm/instructions/system.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) System Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,57 +16,72 @@ Implementations of the EVM system related instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require arrow_glacier.fork_types. -Require arrow_glacier.state. -Require arrow_glacier.utils.address. -Require arrow_glacier.vm.exceptions. -Require arrow_glacier.vm.gas. -Require arrow_glacier.vm.memory. -Require arrow_glacier.vm.stack. - -Definition generic_create : M unit := +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* evm.["accessed_addresses"].["add"] (| + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "add" |) ~(| contract_address - |) in - let* create_message_gas := gas.max_message_call_gas (| - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |) - |) in - (* TODO statement *) + |) ]] 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 *) - let* sender_address := evm.["message"].["current_target"] in - let* sender := state.get_account (| - evm.["env"].["state"], - sender_address - |) in - (* TODO statement *) - (* TODO statement *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) in - do* state.increment_nonce (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |) in - let* child_message := Message (| - - |) in - let* child_evm := process_create_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - - -Definition create : M unit := + 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. @@ -74,42 +90,58 @@ Definition create : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_contract_address (| - evm.["message"].["current_target"], - state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["nonce"] - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition create2 (evm : Evm) : M unit := (* Creates a new account with associated code. @@ -121,50 +153,70 @@ Definition create2 : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* salt := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* call_data_words := (* TODO expression *) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_create2_contract_address (| - evm.["message"].["current_target"], - salt, - memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size - |) in - (* TODO statement *) - + 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_ : M unit := +Definition return_ (evm : Evm) : M unit := (* Halts execution returning output data. @@ -173,66 +225,84 @@ Definition return_ : M unit := evm : The current EVM frame. *) - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) + |) ]] 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 : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_input_start_position, - memory_input_size - |) in - let* code := state.get_account (| - evm.["env"].["state"], - code_address - |).["code"] in - let* child_message := Message (| - - |) in - let* child_evm := process_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - let* actual_output_size := min (| - memory_output_size, - ethereum_types.numeric.U256 (| - len (| - child_evm.["output"] + 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 - do* memory.memory_write (| - evm.["memory"], + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), memory_output_start_position, (* TODO expression *) - |) in + |) ]] in + M.pure tt. - -Definition call : M unit := +Definition call (evm : Evm) : M unit := (* Message-call into an account. @@ -241,62 +311,92 @@ Definition call : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* create_gas_cost := (* TODO expression *) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition callcode (evm : Evm) : M unit := (* Message-call into this account with alternative account’s code. @@ -305,61 +405,91 @@ Definition callcode : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* to := evm.["message"].["current_target"] in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) - (* TODO statement *) - + |) ]] 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 : M unit := +Definition selfdestruct (evm : Evm) : M unit := (* Halt execution and register account for later deletion. @@ -368,49 +498,59 @@ Definition selfdestruct : M unit := evm : The current EVM frame. *) - let* beneficiary := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* gas_cost := gas.GAS_SELF_DESTRUCT in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - (* TODO statement *) - let* originator := evm.["message"].["current_target"] in - let* beneficiary_balance := state.get_account (| - evm.["env"].["state"], - beneficiary - |).["balance"] in - let* originator_balance := state.get_account (| - evm.["env"].["state"], - originator - |).["balance"] in - do* state.set_account_balance (| - evm.["env"].["state"], - beneficiary, + 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 (| - evm.["env"].["state"], - originator, - ethereum_types.numeric.U256 (| - (* 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* evm.["accounts_to_delete"].["add"] (| - originator - |) in + |) ]] 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 : M unit := +Definition delegatecall (evm : Evm) : M unit := (* Message-call into an account. @@ -419,67 +559,89 @@ Definition delegatecall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - access_gas_cost - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - evm.["message"].["value"], - evm.["message"].["caller"], - evm.["message"].["current_target"], - code_address, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition staticcall (evm : Evm) : M unit := (* Message-call into an account. @@ -488,69 +650,91 @@ Definition staticcall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - access_gas_cost - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - ethereum_types.numeric.U256 (| - (* TODO expression *) + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 |), - evm.["message"].["current_target"], - to, - to, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +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 @@ -559,27 +743,37 @@ Definition revert : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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, - extend_memory.["cost"] - |) in - (* TODO statement *) - let* output := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in + 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.v b/coq/ethereum/arrow_glacier/vm/interpreter.v index 926ba43393..760d983860 100644 --- a/coq/ethereum/arrow_glacier/vm/interpreter.v +++ b/coq/ethereum/arrow_glacier/vm/interpreter.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Interpreter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +18,18 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.trace. -Require arrow_glacier.blocks. -Require arrow_glacier.fork_types. -Require arrow_glacier.state. -Require arrow_glacier.vm. -Require arrow_glacier.vm.gas. -Require arrow_glacier.vm.precompiled_contracts.mapping. -Require arrow_glacier.vm.exceptions. -Require arrow_glacier.vm.instructions. -Require arrow_glacier.vm.runtime. - -Definition process_message_call : M unit := +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`. @@ -47,19 +49,21 @@ Definition process_message_call : M unit := *) (* TODO statement *) (* TODO statement *) - let* tx_end := ethereum.trace.TransactionEnd (| - (* TODO expression *), - evm.["output"], - evm.["error"] - |) in - do* ethereum.trace.evm_trace (| - evm, - tx_end - |) in + 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 : M unit := +Definition process_create_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -75,30 +79,32 @@ Definition process_create_message : M unit := evm: :py:class:`~ethereum.london.vm.Evm` Items containing execution specific objects. *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.destroy_storage (| - env.["state"], - message.["current_target"] - |) in - do* state.mark_account_created (| - env.["state"], - message.["current_target"] - |) in - do* state.increment_nonce (| - env.["state"], - message.["current_target"] - |) in - let* evm := process_message (| - message, - env - |) in + 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 : M unit := +Definition process_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -115,23 +121,25 @@ Definition process_message : M unit := Items containing execution specific objects *) (* TODO statement *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.touch_account (| - env.["state"], - message.["current_target"] - |) in + 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 *) - let* evm := execute_code (| - message, - env - |) in + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition execute_code : M unit := +Definition execute_code (message : Message) (env : Environment) : M Evm := (* Executes bytecode present in the `message`. @@ -147,13 +155,19 @@ Definition execute_code : M unit := evm: `ethereum.vm.EVM` Items containing execution specific objects *) - let* code := message.["code"] in - let* valid_jump_destinations := runtime.get_valid_jump_destinations (| - code - |) in - let* evm := Evm (| - - |) in + 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.v b/coq/ethereum/arrow_glacier/vm/memory.v index 94b6a44639..88b516318f 100644 --- a/coq/ethereum/arrow_glacier/vm/memory.v +++ b/coq/ethereum/arrow_glacier/vm/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.byte. -Definition memory_write : M unit := +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := (* Writes to memory. @@ -30,9 +31,9 @@ Definition memory_write : M unit := Data to write to memory. *) (* TODO assignment *) + M.pure tt. - -Definition memory_read_bytes : M unit := +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := (* Read bytes from memory. @@ -51,9 +52,9 @@ Definition memory_read_bytes : M unit := Data read from memory. *) (* TODO statement *) + M.pure tt. - -Definition buffer_read : M unit := +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := (* Read bytes from a buffer. Padding with zeros if necessary. @@ -72,4 +73,4 @@ Definition buffer_read : M unit := Data read from memory. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.v index 065fa245fc..ca8d08f70e 100644 --- a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,4 +14,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require arrow_glacier.utils.hexadecimal. +Require ethereum.arrow_glacier.utils.hexadecimal. diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.v index dae5e63069..b5ef656727 100644 --- a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.v +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,12 +15,12 @@ Implementation of the ALT_BN128 precompiled contracts. Require ethereum_types.numeric. Require ethereum.crypto.alt_bn128. -Require arrow_glacier.vm. -Require arrow_glacier.vm.gas. -Require arrow_glacier.vm.memory. -Require arrow_glacier.vm.exceptions. +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 : M unit := +Definition alt_bn128_add (evm : Evm) : M unit := (* The ALT_BN128 addition precompiled contract. @@ -28,76 +29,96 @@ Definition alt_bn128_add : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* x1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x1_bytes - |) - |) in - let* y1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y1_bytes - |) - |) in + 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 *) - let* p := (* TODO expression *) in + do* M.assign "p" [[ + (* TODO expression *) in + ]] in (* TODO assignment *) + M.pure tt. - -Definition alt_bn128_mul : M unit := +Definition alt_bn128_mul (evm : Evm) : M unit := (* The ALT_BN128 multiplication precompiled contract. @@ -106,63 +127,77 @@ Definition alt_bn128_mul : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* n := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) (* TODO statement *) - let* p := p0.["mul_by"] (| - n - |) in + 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 : M unit := +Definition alt_bn128_pairing_check (evm : Evm) : M unit := (* The ALT_BN128 pairing check precompiled contract. @@ -171,17 +206,21 @@ Definition alt_bn128_pairing_check : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 (| + ethereum_types.numeric.Uint ~(| (* TODO expression *) |) - |) in + |) ]] in (* TODO statement *) - let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.v index f5e7a7d04d..2ae5a638c5 100644 --- a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.v +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,11 @@ Implementation of the `Blake2` precompiled contract. *) Require ethereum.crypto.blake2. -Require arrow_glacier.vm. -Require arrow_glacier.vm.gas. -Require arrow_glacier.vm.exceptions. +Require ethereum.arrow_glacier.vm. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.exceptions. -Definition blake2f : M unit := +Definition blake2f (evm : Evm) : M unit := (* Writes the Blake2 hash to output. @@ -26,16 +27,20 @@ Definition blake2f : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in (* TODO statement *) - let* blake2b := ethereum.crypto.blake2.Blake2b (| + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| - |) in + |) in + ]] in (* TODO assignment *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, (* TODO expression *) - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.v index d76f2ac095..b888925e4e 100644 --- a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.v +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,11 +17,11 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require arrow_glacier.vm. -Require arrow_glacier.vm.gas. -Require arrow_glacier.vm.memory. +Require ethereum.arrow_glacier.vm. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.memory. -Definition ecrecover : M unit := +Definition ecrecover (evm : Evm) : M unit := (* Decrypts the address using elliptic curve DSA recovery mechanism and writes the address to output. @@ -30,64 +31,80 @@ Definition ecrecover : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* message_hash_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* message_hash := ethereum.crypto.hash.Hash32 (| - message_hash_bytes - |) in - let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + ethereum_types.numeric.U256 ~(| + 32 |) - |) - |) in - let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 + ]] 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 *) - let* address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/identity.v index d05dadd70e..f36654cccc 100644 --- a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/identity.v +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/identity.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,10 @@ Implementation of the `IDENTITY` precompiled contract. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require arrow_glacier.vm. -Require arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm. +Require ethereum.arrow_glacier.vm.gas. -Definition identity : M unit := +Definition identity (evm : Evm) : M unit := (* Writes the message data to output. @@ -26,11 +27,15 @@ Definition identity : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.v index 94773a3daf..3d3ba315ea 100644 --- a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.v +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Mapping of precompiled contracts their implementations. *) Require typing. -Require arrow_glacier.fork_types. -Require arrow_glacier.vm.precompiled_contracts.alt_bn128. -Require arrow_glacier.vm.precompiled_contracts.blake2f. -Require arrow_glacier.vm.precompiled_contracts.ecrecover. -Require arrow_glacier.vm.precompiled_contracts.identity. -Require arrow_glacier.vm.precompiled_contracts.modexp. -Require arrow_glacier.vm.precompiled_contracts.ripemd160. -Require arrow_glacier.vm.precompiled_contracts.sha256. +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.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.v index 1ee6b3fa6d..18b26d0ed0 100644 --- a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.v +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,100 +15,120 @@ Implementation of the `MODEXP` precompiled contract. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require arrow_glacier.vm. -Require arrow_glacier.vm.gas. -Require arrow_glacier.vm.memory. +Require ethereum.arrow_glacier.vm. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.memory. -Definition modexp : M unit := +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. *) - let* data := evm.["message"].["data"] in - let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) - |) in - let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 - let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* exp_start := (* TODO expression *) in - let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - min (| - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 |), - exp_length + ethereum_types.numeric.U256 ~(| + 32 + |) |) - |) - |) in - do* vm.gas.charge_gas (| + |) 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, - gas_cost (| - base_length, - modulus_length, - exp_length, - exp_head + 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 + |) ]] in (* TODO statement *) - let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - base_length - |) - |) in - let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - exp_length - |) - |) in - let* modulus_start := (* TODO expression *) in - let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - modulus_start, - modulus_length - |) - |) in + 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 : M unit := +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := (* Estimate the complexity of performing a modular exponentiation. @@ -126,19 +147,23 @@ Definition complexity : M unit := complexity : `Uint` Complexity of performing the operation. *) - let* max_length := max (| - ethereum_types.numeric.Uint (| - base_length - |), - ethereum_types.numeric.Uint (| - modulus_length - |) - |) in - let* words := (* TODO expression *) in + 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 : M unit := +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := (* Calculate the number of iterations required to perform a modular exponentiation. @@ -161,9 +186,9 @@ Definition iterations : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition gas_cost : M unit := +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. @@ -189,15 +214,23 @@ Definition gas_cost : M unit := gas_cost : `Uint` Gas required for performing the operation. *) - let* multiplication_complexity := complexity (| - base_length, - modulus_length - |) in - let* iteration_count := iterations (| - exponent_length, - exponent_head - |) in - let* cost := (* TODO expression *) in - (* TODO statement *) + 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.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.v index bc5e73dd3c..fe2c66bbe6 100644 --- a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.v +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `RIPEMD160` precompiled contract. *) -Definition ripemd160 : M unit := +Definition ripemd160 (evm : Evm) : M unit := (* Writes the ripemd160 hash to output. @@ -22,21 +23,29 @@ Definition ripemd160 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 - let* hash_bytes := hashlib.["new"] (| - (* TODO expression *), - data - |).["digest"] (| - - |) in - let* padded_hash := left_pad_zero_bytes (| - hash_bytes, - (* TODO expression *) - |) in + |) ]] 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.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.v index da6972d411..3ba3ffe7aa 100644 --- a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.v +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `SHA256` precompiled contract. *) -Definition sha256 : M unit := +Definition sha256 (evm : Evm) : M unit := (* Writes the sha256 hash to output. @@ -22,11 +23,15 @@ Definition sha256 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/runtime.v b/coq/ethereum/arrow_glacier/vm/runtime.v index 03107cd8d3..3644a412c3 100644 --- a/coq/ethereum/arrow_glacier/vm/runtime.v +++ b/coq/ethereum/arrow_glacier/vm/runtime.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Runtime Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Runtime related operations used while executing EVM code. Require typing. Require ethereum_types.numeric. -Require arrow_glacier.vm.instructions. +Require ethereum.arrow_glacier.vm.instructions. -Definition get_valid_jump_destinations : M unit := +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := (* Analyze the evm code to obtain the set of valid jump destinations. @@ -38,12 +39,16 @@ Definition get_valid_jump_destinations : M unit := valid_jump_destinations: `Set[Uint]` The set of valid jump destinations in the code. *) - let* valid_jump_destinations := set (| - - |) in - let* pc := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/arrow_glacier/vm/stack.v index c58d560b13..a1b907222b 100644 --- a/coq/ethereum/arrow_glacier/vm/stack.v +++ b/coq/ethereum/arrow_glacier/vm/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Implementation of the stack operators for the EVM. Require typing. Require ethereum_types.numeric. -Require arrow_glacier.vm.exceptions. +Require ethereum.arrow_glacier.vm.exceptions. -Definition pop : M unit := +Definition pop (stack : (* TODO type *)) : M U256 := (* Pops the top item off of `stack`. @@ -33,9 +34,9 @@ Definition pop : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition push : M unit := +Definition push (stack : (* TODO type *)) (value : U256) : M unit := (* Pushes `value` onto `stack`. @@ -50,4 +51,4 @@ Definition push : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/berlin/__init__.v b/coq/ethereum/berlin/__init__.v index 1559435fd6..3ae2342594 100644 --- a/coq/ethereum/berlin/__init__.v +++ b/coq/ethereum/berlin/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* The Berlin fork adjusts the gas costs of the `ModExp` precompile and several state access EVM instructions, introduces typed transaction envelopes along diff --git a/coq/ethereum/berlin/blocks.v b/coq/ethereum/berlin/blocks.v index 718999995d..69c606999d 100644 --- a/coq/ethereum/berlin/blocks.v +++ b/coq/ethereum/berlin/blocks.v @@ -1,3 +1,4 @@ +(* 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 @@ -14,6 +15,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. -Require berlin.fork_types. -Require berlin.transactions. +Require ethereum.crypto.hash. +Require ethereum.berlin.fork_types. +Require ethereum.berlin.transactions. diff --git a/coq/ethereum/berlin/bloom.v b/coq/ethereum/berlin/bloom.v index e37d9e9866..d3ecba981b 100644 --- a/coq/ethereum/berlin/bloom.v +++ b/coq/ethereum/berlin/bloom.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Logs Bloom ^^^^^^^^^^^^^^^^^^^ @@ -19,10 +20,10 @@ eliminating blocks and receipts from their search. Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require berlin.blocks. -Require berlin.fork_types. +Require ethereum.berlin.blocks. +Require ethereum.berlin.fork_types. -Definition add_to_bloom : M unit := +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := (* Add a bloom entry to the bloom filter (`bloom`). @@ -37,13 +38,15 @@ Definition add_to_bloom : M unit := bloom_entry : An entry which is to be added to bloom filter. *) - let* hash := ethereum.crypto.hash.keccak256 (| - bloom_entry - |) in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition logs_bloom : M unit := +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := (* Obtain the logs bloom from a list of log entries. @@ -63,4 +66,4 @@ Definition logs_bloom : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/berlin/exceptions.v b/coq/ethereum/berlin/exceptions.v index 137ea143f6..9a313f6d0e 100644 --- a/coq/ethereum/berlin/exceptions.v +++ b/coq/ethereum/berlin/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Exceptions specific to this fork. *) diff --git a/coq/ethereum/berlin/fork.v b/coq/ethereum/berlin/fork.v index 7225636763..f2e5ffdc2a 100644 --- a/coq/ethereum/berlin/fork.v +++ b/coq/ethereum/berlin/fork.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^ @@ -20,16 +21,18 @@ Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.ethash. Require ethereum.exceptions. -Require berlin.blocks. -Require berlin.bloom. -Require berlin.fork_types. -Require berlin.state. -Require berlin.transactions. -Require berlin.trie. -Require berlin.utils.message. -Require berlin.vm.interpreter. - -Definition apply_fork : M unit := +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. @@ -49,9 +52,9 @@ Definition apply_fork : M unit := Upgraded block chain object for this hard fork. *) (* TODO statement *) + M.pure tt. - -Definition get_last_256_block_hashes : M unit := +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. @@ -71,22 +74,28 @@ Definition get_last_256_block_hashes : M unit := recent_block_hashes : `List[Hash32]` Hashes of the recent 256 blocks in order of increasing block number. *) - let* recent_blocks := (* TODO expression *) in - (* TODO statement *) - let* recent_block_hashes := (* TODO expression *) in - (* TODO statement *) - let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *).["header"] - |) - |) in - do* recent_block_hashes.["append"] (| - most_recent_block_hash - |) in - (* TODO statement *) - - -Definition state_transition : M unit := + 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. @@ -108,42 +117,46 @@ Definition state_transition : M unit := block : Block to apply to `chain`. *) - let* parent_header := (* TODO expression *).["header"] in - do* validate_header (| - block.["header"], - parent_header - |) in - do* validate_ommers (| - block.["ommers"], - block.["header"], + 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 - let* apply_body_output := apply_body (| - chain.["state"], - get_last_256_block_hashes (| - chain - |), - block.["header"].["coinbase"], - block.["header"].["number"], - block.["header"].["gas_limit"], - block.["header"].["timestamp"], - block.["header"].["difficulty"], - block.["transactions"], - block.["ommers"], - chain.["chain_id"] - |) in + |) ]] 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* chain.["blocks"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| block - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition validate_header : M unit := +Definition validate_header (header : Header) (parent_header : Header) : M unit := (* Verifies a block header. @@ -161,31 +174,37 @@ Definition validate_header : M unit := parent_header : Parent Header of the header to check for correctness *) - let* parent_has_ommers := (* TODO expression *) in + do* M.assign "parent_has_ommers" [[ + (* TODO expression *) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* block_difficulty := calculate_block_difficulty (| - header.["number"], - header.["timestamp"], - parent_header.["timestamp"], - parent_header.["difficulty"], - parent_has_ommers - |) in + 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 *) - let* block_parent_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - parent_header - |) - |) in + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in (* TODO statement *) - do* validate_proof_of_work (| + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| header - |) in - + |) ]] in + M.pure tt. -Definition generate_header_hash_for_pow : M unit := +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. @@ -208,11 +227,13 @@ Definition generate_header_hash_for_pow : M unit := hash : `Hash32` The PoW valid rlp hash of the passed in header. *) - let* header_data_without_pow_artefacts := (* TODO expression *) in + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition validate_proof_of_work : M unit := +Definition validate_proof_of_work (header : Header) : M unit := (* Validates the Proof of Work constraints. @@ -227,19 +248,25 @@ Definition validate_proof_of_work : M unit := header : Header of interest. *) - let* header_hash := generate_header_hash_for_pow (| - header - |) in - let* cache := ethereum.ethash.generate_cache (| - header.["number"] - |) in + 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 *) - let* limit := (* TODO expression *) in + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition check_transaction : M unit := +Definition check_transaction (tx : Transaction) (gas_available : Uint) (chain_id : U64) : M Address := (* Check if the transaction is includable in the block. @@ -263,14 +290,16 @@ Definition check_transaction : M unit := If the transaction is not includable. *) (* TODO statement *) - let* sender_address := recover_sender (| - chain_id, - tx - |) in + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition make_receipt : M unit := +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. @@ -291,13 +320,15 @@ Definition make_receipt : M unit := receipt : The receipt for the transaction. *) - let* receipt := blocks.Receipt (| + do* M.assign "receipt" [[ + blocks.Receipt ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition apply_body : M unit := +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. @@ -338,25 +369,31 @@ Definition apply_body : M unit := apply_body_output : `ApplyBodyOutput` Output of applying the block body to the state. *) - let* gas_available := block_gas_limit in + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - do* pay_rewards (| + do* [[ M.get_local ~(| "pay_rewards" |) ~(| state, block_number, coinbase, ommers - |) in - let* block_gas_used := (* TODO expression *) in - let* block_logs_bloom := bloom.logs_bloom (| - block_logs - |) in - (* TODO statement *) - - -Definition validate_ommers : M unit := + |) ]] 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. @@ -378,23 +415,31 @@ Definition validate_ommers : M unit := chain : History and current state. *) - let* block_hash := rlp.["rlp_hash"] (| - block_header - |) in + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* ommers_hashes := (* TODO expression *) in + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* recent_canonical_blocks := (* TODO expression *) in - let* recent_canonical_block_hashes := (* TODO expression *) in + 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 : M unit := +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. @@ -420,21 +465,25 @@ Definition pay_rewards : M unit := ommers : List of ommers mentioned in the current block. *) - let* ommer_count := ethereum_types.numeric.U256 (| - len (| - ommers - |) - |) in - let* miner_reward := (* TODO expression *) in - do* state.create_ether (| + 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, - miner_reward - |) in + M.get_local ~(| "miner_reward" |) + |) ]] in (* TODO statement *) + M.pure tt. - -Definition process_transaction : M unit := +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := (* Execute a transaction against the provided environment. @@ -462,71 +511,103 @@ Definition process_transaction : M unit := Logs generated during execution. *) (* TODO statement *) - let* sender := env.["origin"] in - let* sender_account := state.get_account (| - env.["state"], - sender - |) in - let* gas_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* gas := (* TODO expression *) in - do* state.increment_nonce (| - env.["state"], - sender - |) in - let* sender_balance_after_gas_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - ethereum_types.numeric.U256 (| - sender_balance_after_gas_fee - |) - |) in - let* preaccessed_addresses := set (| - - |) in - let* preaccessed_storage_keys := set (| - - |) in - (* TODO statement *) - let* message := utils.message.prepare_message (| - sender, - tx.["to"], - tx.["value"], - tx.["data"], - gas, - env - |) in - let* output := vm.interpreter.process_message_call (| - message, - env - |) in - let* gas_used := (* TODO expression *) in - let* gas_refund := min (| - (* TODO expression *), - ethereum_types.numeric.Uint (| - output.["refund_counter"] + 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 - let* gas_refund_amount := (* TODO expression *) in - let* transaction_fee := (* TODO expression *) in - let* total_gas_used := (* TODO expression *) in - let* sender_balance_after_refund := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - sender_balance_after_refund - |) in - let* coinbase_balance_after_mining_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - - -Definition validate_transaction : M unit := + |) ]] 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. @@ -554,9 +635,9 @@ Definition validate_transaction : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition calculate_intrinsic_cost : M unit := +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := (* Calculates the gas that is charged before execution is started. @@ -579,15 +660,19 @@ Definition calculate_intrinsic_cost : M unit := verified : `ethereum.base_types.Uint` The intrinsic cost of the transaction. *) - let* data_cost := (* TODO expression *) in + do* M.assign "data_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) - let* access_list_cost := (* TODO expression *) in + do* M.assign "access_list_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition recover_sender : M unit := +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := (* Extracts the sender address from a transaction. @@ -614,9 +699,9 @@ Definition recover_sender : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_pre155 : M unit := +Definition signing_hash_pre155 (tx : Transaction) : M Hash32 := (* Compute the hash of a transaction used in a legacy (pre EIP 155) signature. @@ -631,9 +716,9 @@ Definition signing_hash_pre155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_155 : M unit := +Definition signing_hash_155 (tx : Transaction) (chain_id : U64) : M Hash32 := (* Compute the hash of a transaction used in a EIP 155 signature. @@ -650,9 +735,9 @@ Definition signing_hash_155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_2930 : M unit := +Definition signing_hash_2930 (tx : AccessListTransaction) : M Hash32 := (* Compute the hash of a transaction used in a EIP 2930 signature. @@ -667,9 +752,9 @@ Definition signing_hash_2930 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition compute_header_hash : M unit := +Definition compute_header_hash (header : Header) : M Hash32 := (* Computes the hash of a block header. @@ -702,9 +787,9 @@ Definition compute_header_hash : M unit := Hash of the header. *) (* TODO statement *) + M.pure tt. - -Definition check_gas_limit : M unit := +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := (* Validates the gas limit for a block. @@ -732,14 +817,16 @@ Definition check_gas_limit : M unit := check : `bool` True if gas limit constraints are satisfied, False otherwise. *) - let* max_adjustment_delta := (* TODO expression *) in + 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 : M unit := +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. @@ -778,9 +865,15 @@ Definition calculate_block_difficulty : M unit := difficulty : `ethereum.base_types.Uint` Computed difficulty for a block. *) - let* offset := (* TODO expression *) in - let* difficulty := (* TODO expression *) in - let* num_bomb_periods := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - + 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.v b/coq/ethereum/berlin/fork_types.v index 14de99d5e5..d84cffdf45 100644 --- a/coq/ethereum/berlin/fork_types.v +++ b/coq/ethereum/berlin/fork_types.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Types ^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. +Require ethereum.__init__. +Require ethereum.crypto.hash. -Definition encode_account : M unit := +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := (* Encode `Account` dataclass. @@ -26,4 +28,4 @@ Definition encode_account : M unit := encoded without providing a storage root. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/berlin/state.v b/coq/ethereum/berlin/state.v index 34ee56c18a..c6e132c46f 100644 --- a/coq/ethereum/berlin/state.v +++ b/coq/ethereum/berlin/state.v @@ -1,3 +1,4 @@ +(* Generated *) (* State ^^^^^ @@ -22,10 +23,10 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require berlin.fork_types. -Require berlin.trie. +Require ethereum.berlin.fork_types. +Require ethereum.berlin.trie. -Definition close_state : M unit := +Definition close_state (state : State) : M unit := (* Free resources held by the state. Used by optimized implementations to release file descriptors. @@ -34,9 +35,9 @@ Definition close_state : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition begin_transaction : M unit := +Definition begin_transaction (state : State) : M unit := (* Start a state transaction. @@ -48,12 +49,12 @@ Definition begin_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition commit_transaction : M unit := +Definition commit_transaction (state : State) : M unit := (* Commit a state transaction. @@ -62,13 +63,13 @@ Definition commit_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["pop"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition rollback_transaction : M unit := +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. @@ -80,9 +81,9 @@ Definition rollback_transaction : M unit := *) (* TODO assignment *) (* TODO statement *) + M.pure tt. - -Definition get_account : M unit := +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. @@ -102,14 +103,16 @@ Definition get_account : M unit := account : `Account` Account at address. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition get_account_optional : M unit := +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. @@ -126,14 +129,16 @@ Definition get_account_optional : M unit := account : `Account` Account at address. *) - let* account := trie.trie_get (| - state.["_main_trie"], - address - |) in + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition set_account : M unit := +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()`). @@ -147,14 +152,14 @@ Definition set_account : M unit := account : `Account` Account to set at address. *) - do* trie.trie_set (| - state.["_main_trie"], + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), address, account - |) in + |) ]] in + M.pure tt. - -Definition destroy_account : M unit := +Definition destroy_account (state : State) (address : Address) : M unit := (* Completely remove the account at `address` and all of its storage. @@ -169,18 +174,18 @@ Definition destroy_account : M unit := address : `Address` Address of account to destroy. *) - do* destroy_storage (| + do* [[ M.get_local ~(| "destroy_storage" |) ~(| state, address - |) in - do* set_account (| + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - (* TODO expression *) - |) in + tt + |) ]] in + M.pure tt. - -Definition destroy_storage : M unit := +Definition destroy_storage (state : State) (address : Address) : M unit := (* Completely remove the storage at `address`. @@ -192,9 +197,9 @@ Definition destroy_storage : M unit := Address of account whose storage is to be deleted. *) (* TODO statement *) + M.pure tt. - -Definition mark_account_created : M unit := +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 @@ -211,12 +216,12 @@ Definition mark_account_created : M unit := address : `Address` Address of the account that has been created. *) - do* state.["created_accounts"].["add"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| address - |) in - + |) ]] in + M.pure tt. -Definition get_storage : M unit := +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. @@ -235,19 +240,23 @@ Definition get_storage : M unit := value : `U256` Value at the key. *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition set_storage : M unit := +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. @@ -264,19 +273,21 @@ Definition set_storage : M unit := Value to set at the key. *) (* TODO statement *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - do* trie.trie_set (| - trie, + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), key, value - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition storage_root : M unit := +Definition storage_root (state : State) (address : Address) : M Root := (* Calculate the storage root of an account. @@ -294,9 +305,9 @@ Definition storage_root : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition state_root : M unit := +Definition state_root (state : State) : M Root := (* Calculate the state root. @@ -313,9 +324,9 @@ Definition state_root : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition account_exists : M unit := +Definition account_exists (state : State) (address : Address) : M bool := (* Checks if an account exists in the state trie @@ -332,9 +343,9 @@ Definition account_exists : M unit := True if account exists in the state trie, False otherwise *) (* TODO statement *) + M.pure tt. - -Definition account_has_code_or_nonce : M unit := +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := (* Checks if an account has non zero nonce or non empty code @@ -351,14 +362,16 @@ Definition account_has_code_or_nonce : M unit := True if if an account has non zero nonce or non empty code, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_empty : M unit := +Definition is_account_empty (state : State) (address : Address) : M bool := (* Checks if an account has zero nonce, empty code and zero balance. @@ -375,14 +388,16 @@ Definition is_account_empty : M unit := True if if an account has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition account_exists_and_is_empty : M unit := +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. @@ -400,14 +415,16 @@ Definition account_exists_and_is_empty : M unit := True if an account exists and has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_alive : M unit := +Definition is_account_alive (state : State) (address : Address) : M bool := (* Check whether is an account is both in the state and non empty. @@ -423,49 +440,51 @@ Definition is_account_alive : M unit := is_alive : `bool` True if the account is alive. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition modify_state : M unit := +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := (* Modify an `Account` in the `State`. *) - do* set_account (| + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - ethereum_types.frozen.modify (| - get_account (| + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| state, address |), f |) - |) in - + |) ]] in + M.pure tt. -Definition move_ether : M unit := +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := (* Move funds between accounts. *) (* TODO statement *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, sender_address, - reduce_sender_balance - |) in - do* modify_state (| + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| state, recipient_address, - increase_recipient_balance - |) in - + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. -Definition set_account_balance : M unit := +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := (* Sets the balance of an account. @@ -481,14 +500,14 @@ Definition set_account_balance : M unit := The amount that needs to set in balance. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - set_balance - |) in + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. - -Definition touch_account : M unit := +Definition touch_account (state : State) (address : Address) : M unit := (* Initializes an account to state. @@ -501,9 +520,9 @@ Definition touch_account : M unit := The address of the account that need to initialised. *) (* TODO statement *) + M.pure tt. - -Definition increment_nonce : M unit := +Definition increment_nonce (state : State) (address : Address) : M unit := (* Increments the nonce of an account. @@ -516,14 +535,14 @@ Definition increment_nonce : M unit := Address of the account whose nonce needs to be incremented. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_nonce - |) in + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. - -Definition set_code : M unit := +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := (* Sets Account code. @@ -539,14 +558,14 @@ Definition set_code : M unit := The bytecode that needs to be set. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - write_code - |) in - + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. -Definition create_ether : M unit := +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := (* Add newly created ether to an account. @@ -560,14 +579,14 @@ Definition create_ether : M unit := The amount of ether to be added to the account of interest. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_balance - |) in - + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. -Definition get_storage_original : M unit := +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 @@ -584,10 +603,12 @@ Definition get_storage_original : M unit := *) (* TODO statement *) (* TODO assignment *) - let* original_account_trie := original_trie.["get"] (| - address - |) in + 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.v b/coq/ethereum/berlin/transactions.v index 18237477b5..2e04a2a104 100644 --- a/coq/ethereum/berlin/transactions.v +++ b/coq/ethereum/berlin/transactions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, @@ -9,19 +10,20 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require berlin.exceptions. -Require berlin.fork_types. +Require ethereum.__init__. +Require ethereum.berlin.exceptions. +Require ethereum.berlin.fork_types. -Definition encode_transaction : M unit := +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 : M unit := +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.v b/coq/ethereum/berlin/trie.v index 3e073bba06..2e36b195fc 100644 --- a/coq/ethereum/berlin/trie.v +++ b/coq/ethereum/berlin/trie.v @@ -1,3 +1,4 @@ +(* Generated *) (* State Trie ^^^^^^^^^^ @@ -14,7 +15,7 @@ The state trie is the structure responsible for storing *) -Definition encode_internal_node : M unit := +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 @@ -35,22 +36,24 @@ Definition encode_internal_node : M unit := *) (* TODO statement *) (* TODO statement *) - let* encoded := rlp.["encode"] (| - unencoded - |) in + 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 : M unit := +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 : M unit := +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. @@ -66,9 +69,9 @@ Definition copy_trie : M unit := A copy of the trie. *) (* TODO statement *) + M.pure tt. - -Definition trie_set : M unit := +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := (* Stores an item in a Merkle Trie. @@ -85,9 +88,9 @@ Definition trie_set : M unit := Node to insert at `key`. *) (* TODO statement *) + M.pure tt. - -Definition trie_get : M unit := +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := (* Gets an item from the Merkle Trie. @@ -106,17 +109,17 @@ Definition trie_get : M unit := Node at `key` in the trie. *) (* TODO statement *) + M.pure tt. - -Definition common_prefix_length : M unit := +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 : M unit := +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := (* Compresses nibble-list into a standard byte array with a flag. @@ -150,14 +153,16 @@ Definition nibble_list_to_compact : M unit := compressed : `bytearray` Compact byte array. *) - let* compact := bytearray (| + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition bytes_to_nibble_list : M unit := +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := (* Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). @@ -171,14 +176,16 @@ Definition bytes_to_nibble_list : M unit := nibble_list : `Bytes` The `Bytes` in nibble-list format. *) - let* nibble_list := bytearray (| - (* TODO expression *) - |) in + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _prepare_trie : M unit := +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. @@ -199,9 +206,9 @@ Definition _prepare_trie : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition root : M unit := +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := (* Computes the root of a modified merkle patricia trie (MPT). @@ -219,22 +226,26 @@ Definition root : M unit := root : `eth1spec.fork_types.Root` MPT root of the underlying key-value pairs. *) - let* obj := _prepare_trie (| - trie, - get_storage_root - |) in - let* root_node := encode_internal_node (| - patricialize (| - obj, - Uint (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) + M.pure tt. - -Definition patricialize : M unit := +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := (* Structural composition function. @@ -254,21 +265,29 @@ Definition patricialize : M unit := Root node of `obj`. *) (* TODO statement *) - let* arbitrary_key := next (| - iter (| - obj - |) - |) in + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in (* TODO statement *) - let* substring := (* TODO expression *) in - let* prefix_length := len (| - substring - |) in + 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 *) - let* value := (* TODO expression *) in + do* M.assign "value" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/berlin/utils/__init__.v b/coq/ethereum/berlin/utils/__init__.v index beff4482b1..7f30fe939b 100644 --- a/coq/ethereum/berlin/utils/__init__.v +++ b/coq/ethereum/berlin/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions unique to this particular fork. *) diff --git a/coq/ethereum/berlin/utils/address.v b/coq/ethereum/berlin/utils/address.v index f90ce3c8d3..81def78a3d 100644 --- a/coq/ethereum/berlin/utils/address.v +++ b/coq/ethereum/berlin/utils/address.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,9 +19,10 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require berlin.fork_types. +Require ethereum.__init__. +Require ethereum.berlin.fork_types. -Definition to_address : M unit := +Definition to_address (data : (* TODO type *)) : M Address := (* Convert a Uint or U256 value to a valid address (20 bytes). @@ -35,9 +37,9 @@ Definition to_address : M unit := The obtained address. *) (* TODO statement *) + M.pure tt. - -Definition compute_contract_address : M unit := +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := (* Computes address of the new account that needs to be created. @@ -54,20 +56,26 @@ Definition compute_contract_address : M unit := address: `Address` The computed address of the new account. *) - let* computed_address := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *) - |) - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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 : M unit := +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. @@ -86,14 +94,22 @@ Definition compute_create2_contract_address : M unit := address: `ethereum.berlin.fork_types.Address` The computed address of the new account. *) - let* preimage := (* TODO expression *) in - let* computed_address := ethereum.crypto.hash.keccak256 (| - preimage - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/berlin/utils/hexadecimal.v index 93fb628067..805db3fa5a 100644 --- a/coq/ethereum/berlin/utils/hexadecimal.v +++ b/coq/ethereum/berlin/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Berlin types. *) Require ethereum.utils.hexadecimal. -Require berlin.fork_types. +Require ethereum.berlin.fork_types. -Definition hex_to_root : M unit := +Definition hex_to_root (hex_string : str) : M Root := (* Convert hex string to trie root. @@ -31,9 +32,9 @@ Definition hex_to_root : M unit := Trie root obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bloom : M unit := +Definition hex_to_bloom (hex_string : str) : M Bloom := (* Convert hex string to bloom. @@ -48,9 +49,9 @@ Definition hex_to_bloom : M unit := Bloom obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_address : M unit := +Definition hex_to_address (hex_string : str) : M Address := (* Convert hex string to Address (20 bytes). @@ -65,4 +66,4 @@ Definition hex_to_address : M unit := The address obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/berlin/utils/message.v b/coq/ethereum/berlin/utils/message.v index 4e996471dc..afbdb95cc4 100644 --- a/coq/ethereum/berlin/utils/message.v +++ b/coq/ethereum/berlin/utils/message.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For The Message Data-structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,13 +17,13 @@ specification. Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require berlin.fork_types. -Require berlin.state. -Require berlin.vm. -Require berlin.vm.precompiled_contracts.mapping. -Require berlin.utils.address. +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 : M unit := +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. @@ -61,22 +62,24 @@ Definition prepare_message : M unit := Items containing contract creation or message call specific data. *) (* TODO statement *) - let* accessed_addresses := set (| + do* M.assign "accessed_addresses" [[ + M.get_local ~(| "set" |) ~(| - |) in - do* accessed_addresses.["add"] (| - current_target - |) in - do* accessed_addresses.["add"] (| + |) 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* accessed_addresses.["update"] (| - vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS.["keys"] (| + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS, "keys" |) ~(| |) - |) in - do* accessed_addresses.["update"] (| + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| preaccessed_addresses - |) in + |) ]] in (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/berlin/vm/__init__.v b/coq/ethereum/berlin/vm/__init__.v index 77fe0bc4ab..8168b47b26 100644 --- a/coq/ethereum/berlin/vm/__init__.v +++ b/coq/ethereum/berlin/vm/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,12 +19,12 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require berlin.blocks. -Require berlin.fork_types. -Require berlin.state. -Require berlin.vm.precompiled_contracts. +Require ethereum.berlin.blocks. +Require ethereum.berlin.fork_types. +Require ethereum.berlin.state. +Require ethereum.berlin.vm.precompiled_contracts. -Definition incorporate_child_on_success : M unit := +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of a successful `child_evm` into the parent `evm`. @@ -34,25 +35,31 @@ Definition incorporate_child_on_success : M unit := 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 *) - (* TODO statement *) - (* TODO statement *) - do* evm.["accounts_to_delete"].["update"] (| - child_evm.["accounts_to_delete"] - |) in - do* evm.["touched_accounts"].["update"] (| - child_evm.["touched_accounts"] - |) in - (* TODO statement *) - do* evm.["accessed_addresses"].["update"] (| - child_evm.["accessed_addresses"] - |) in - do* evm.["accessed_storage_keys"].["update"] (| - child_evm.["accessed_storage_keys"] - |) in + 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 : M unit := +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. @@ -65,5 +72,7 @@ Definition incorporate_child_on_error : M unit := *) (* TODO statement *) (* 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.v b/coq/ethereum/berlin/vm/exceptions.v index 1784494410..47e26555d5 100644 --- a/coq/ethereum/berlin/vm/exceptions.v +++ b/coq/ethereum/berlin/vm/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Exceptions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/berlin/vm/gas.v b/coq/ethereum/berlin/vm/gas.v index 0d2e1de7e8..1ff33a2caf 100644 --- a/coq/ethereum/berlin/vm/gas.v +++ b/coq/ethereum/berlin/vm/gas.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Gas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,9 +18,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.trace. Require ethereum.utils.numeric. -Require berlin.vm.exceptions. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.exceptions. -Definition charge_gas : M unit := +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := (* Subtracts `amount` from `evm.gas_left`. @@ -31,18 +33,18 @@ Definition charge_gas : M unit := The amount of gas the current operation requires. *) - do* ethereum.trace.evm_trace (| + do* [[ ethereum.trace.evm_trace ~(| evm, - ethereum.trace.GasAndRefund (| - int (| + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| amount |) |) - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_memory_gas_cost : M unit := +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, @@ -58,14 +60,22 @@ Definition calculate_memory_gas_cost : M unit := total_gas_cost : `ethereum.base_types.Uint` The gas cost for storing data in memory. *) - let* size_in_words := (* TODO expression *) in - let* linear_cost := (* TODO expression *) in - let* quadratic_cost := (* TODO expression *) in - let* total_gas_cost := (* TODO expression *) in + 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 : M unit := +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := (* Calculates the gas amount to extend memory @@ -81,22 +91,28 @@ Definition calculate_gas_extend_memory : M unit := ------- extend_memory: `ExtendMemory` *) - let* size_to_extend := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* to_be_paid := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* current_size := ethereum_types.numeric.Uint (| - len (| - memory - |) - |) in + 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 : M unit := +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. @@ -122,18 +138,22 @@ Definition calculate_message_call_gas : M unit := ------- message_call_gas: `MessageCallGas` *) - let* call_stipend := (* TODO expression *) in + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* gas := min (| - gas, - max_message_call_gas (| - (* TODO expression *) - |) - |) in + 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 : M unit := +Definition max_message_call_gas (gas : Uint) : M Uint := (* Calculates the maximum gas that is allowed for making a message call @@ -148,4 +168,4 @@ Definition max_message_call_gas : M unit := The maximum gas allowed for making the message-call. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/berlin/vm/instructions/__init__.v b/coq/ethereum/berlin/vm/instructions/__init__.v index b36b1ebfef..cbd7e7e63a 100644 --- a/coq/ethereum/berlin/vm/instructions/__init__.v +++ b/coq/ethereum/berlin/vm/instructions/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* EVM Instruction Encoding (Opcodes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/berlin/vm/instructions/arithmetic.v b/coq/ethereum/berlin/vm/instructions/arithmetic.v index eecb9665f5..1dd92520ff 100644 --- a/coq/ethereum/berlin/vm/instructions/arithmetic.v +++ b/coq/ethereum/berlin/vm/instructions/arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,11 @@ Implementations of the EVM Arithmetic instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require berlin.vm.gas. -Require berlin.vm.stack. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.stack. -Definition add : M unit := +Definition add (evm : Evm) : M unit := (* Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -28,27 +30,37 @@ Definition add : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_add"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sub (evm : Evm) : M unit := (* Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -59,27 +71,37 @@ Definition sub : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_sub"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mul (evm : Evm) : M unit := (* Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -90,27 +112,37 @@ Definition mul : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_mul"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition div (evm : Evm) : M unit := (* Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -121,25 +153,33 @@ Definition div : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |) in - let* divisor := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - quotient - |) 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 : M unit := +Definition sdiv (evm : Evm) : M unit := (* Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -150,31 +190,39 @@ Definition sdiv : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* divisor := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - quotient + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mod : M unit := +Definition mod (evm : Evm) : M unit := (* Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -185,25 +233,33 @@ Definition mod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - remainder - |) in + |) ]] 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 : M unit := +Definition smod (evm : Evm) : M unit := (* Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -214,31 +270,39 @@ Definition smod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* y := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - remainder + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition addmod : M unit := +Definition addmod (evm : Evm) : M unit := (* Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -249,34 +313,44 @@ Definition addmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +Definition mulmod (evm : Evm) : M unit := (* Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -287,34 +361,44 @@ Definition mulmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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 : M unit := +Definition exp (evm : Evm) : M unit := (* Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -325,39 +409,53 @@ Definition exp : M unit := The current EVM frame. *) - let* base := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent_bits := exponent.["bit_length"] (| - - |) in - let* exponent_bytes := (* TODO expression *) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - pow (| - base, - exponent, - (* 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 - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition signextend : M unit := +Definition signextend (evm : Evm) : M unit := (* Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -368,20 +466,28 @@ Definition signextend : M unit := The current EVM frame. *) - let* byte_num := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/berlin/vm/instructions/bitwise.v index 2aaf2749ca..86dded2c4e 100644 --- a/coq/ethereum/berlin/vm/instructions/bitwise.v +++ b/coq/ethereum/berlin/vm/instructions/bitwise.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Bitwise Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM bitwise instructions. *) Require ethereum_types.numeric. -Require berlin.vm.gas. -Require berlin.vm.stack. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.stack. -Definition bitwise_and : M unit := +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. @@ -27,24 +29,32 @@ Definition bitwise_and : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_or : M unit := +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. @@ -55,24 +65,32 @@ Definition bitwise_or : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_xor : M unit := +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. @@ -83,24 +101,32 @@ Definition bitwise_xor : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_not : M unit := +Definition bitwise_not (evm : Evm) : M unit := (* Bitwise NOT operation of the top element of the stack. Pushes the result back on the stack. @@ -111,21 +137,27 @@ Definition bitwise_not : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition get_byte : M unit := +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 @@ -137,25 +169,33 @@ Definition get_byte : M unit := The current EVM frame. *) - let* byte_index := stack.pop (| - evm.["stack"] - |) in - let* word := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -164,29 +204,37 @@ Definition bitwise_shl : M unit := evm : The current EVM frame. *) - let* shift := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -195,25 +243,33 @@ Definition bitwise_shr : M unit := evm : The current EVM frame. *) - let* shift := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -222,24 +278,32 @@ Definition bitwise_sar : M unit := evm : The current EVM frame. *) - let* shift := int (| - stack.pop (| - evm.["stack"] - |) - |) in - let* signed_value := stack.pop (| - evm.["stack"] - |).["to_signed"] (| + 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 - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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.v b/coq/ethereum/berlin/vm/instructions/block.v index b5be147a64..e8f098fa38 100644 --- a/coq/ethereum/berlin/vm/instructions/block.v +++ b/coq/ethereum/berlin/vm/instructions/block.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Block Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM block instructions. *) Require ethereum_types.numeric. -Require berlin.vm.gas. -Require berlin.vm.stack. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.stack. -Definition block_hash : M unit := +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. @@ -27,27 +29,35 @@ Definition block_hash : M unit := The current EVM frame. *) - let* block_number := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* max_block_number := (* TODO expression *) in + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition coinbase : M unit := +Definition coinbase (evm : Evm) : M unit := (* Push the current block's beneficiary address (address of the block miner) onto the stack. @@ -62,20 +72,24 @@ Definition coinbase : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["coinbase"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition timestamp : M unit := +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. @@ -90,18 +104,22 @@ Definition timestamp : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["env"].["time"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition number (evm : Evm) : M unit := (* Push the current block's number onto the stack. @@ -115,20 +133,24 @@ Definition number : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["number"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition difficulty : M unit := +Definition difficulty (evm : Evm) : M unit := (* Push the current block's difficulty onto the stack. @@ -142,20 +164,24 @@ Definition difficulty : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["difficulty"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_limit : M unit := +Definition gas_limit (evm : Evm) : M unit := (* Push the current block's gas limit onto the stack. @@ -169,20 +195,24 @@ Definition gas_limit : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_limit"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition chain_id : M unit := +Definition chain_id (evm : Evm) : M unit := (* Push the chain id onto the stack. @@ -193,15 +223,19 @@ Definition chain_id : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["chain_id"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/berlin/vm/instructions/comparison.v index a74bce325e..4e409de78c 100644 --- a/coq/ethereum/berlin/vm/instructions/comparison.v +++ b/coq/ethereum/berlin/vm/instructions/comparison.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Comparison Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM Comparison instructions. *) Require ethereum_types.numeric. -Require berlin.vm.gas. -Require berlin.vm.stack. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.stack. -Definition less_than : M unit := +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. @@ -27,27 +29,37 @@ Definition less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_less_than : M unit := + |) ]] 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. @@ -57,31 +69,41 @@ Definition signed_less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition greater_than : M unit := + |) ]] 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. @@ -92,27 +114,37 @@ Definition greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_greater_than : M unit := + |) ]] 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. @@ -122,31 +154,41 @@ Definition signed_greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition equal : M unit := + |) ]] 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. @@ -157,27 +199,37 @@ Definition equal : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition is_zero : M unit := + |) ]] 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. @@ -188,19 +240,27 @@ Definition is_zero : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/berlin/vm/instructions/control_flow.v index cf98b07c7b..48cd13d5bb 100644 --- a/coq/ethereum/berlin/vm/instructions/control_flow.v +++ b/coq/ethereum/berlin/vm/instructions/control_flow.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Control Flow Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM control flow instructions. *) Require ethereum_types.numeric. -Require berlin.vm.gas. -Require berlin.vm.exceptions. -Require berlin.vm.stack. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.exceptions. +Require ethereum.berlin.vm.stack. -Definition stop : M unit := +Definition stop (evm : Evm) : M unit := (* Stop further execution of EVM code. @@ -29,10 +31,14 @@ Definition stop : M unit := (* TODO statement *) (* TODO statement *) (* TODO assignment *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jump : M unit := +Definition jump (evm : Evm) : M unit := (* Alter the program counter to the location specified by the top of the stack. @@ -43,20 +49,22 @@ Definition jump : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition jumpi : M unit := +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 @@ -68,23 +76,27 @@ Definition jumpi : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* conditional_value := stack.pop (| - evm.["stack"] - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition pc : M unit := +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. @@ -96,20 +108,24 @@ Definition pc : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["pc"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_left : M unit := +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. @@ -121,20 +137,24 @@ Definition gas_left : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["gas_left"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jumpdest : M unit := +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 @@ -147,10 +167,14 @@ Definition jumpdest : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_JUMPDEST - |) in - (* TODO statement *) + |) ]] 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.v b/coq/ethereum/berlin/vm/instructions/environment.v index 2e255b4efd..c8e0ae64a5 100644 --- a/coq/ethereum/berlin/vm/instructions/environment.v +++ b/coq/ethereum/berlin/vm/instructions/environment.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,15 +16,16 @@ Implementations of the EVM environment related instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require berlin.fork_types. -Require berlin.state. -Require berlin.utils.address. -Require berlin.vm.memory. -Require berlin.vm.exceptions. -Require berlin.vm.gas. -Require berlin.vm.stack. - -Definition address : M unit := +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. @@ -34,20 +36,24 @@ Definition address : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["current_target"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition balance : M unit := +Definition balance (evm : Evm) : M unit := (* Pushes the balance of the given account onto the stack. @@ -57,24 +63,32 @@ Definition balance : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] + 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 - (* TODO statement *) - let* balance := state.get_account (| - evm.["env"].["state"], - address - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition origin : M unit := +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. @@ -86,20 +100,24 @@ Definition origin : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["origin"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition caller : M unit := +Definition caller (evm : Evm) : M unit := (* Pushes the address of the caller onto the stack. @@ -110,20 +128,24 @@ Definition caller : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["caller"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition callvalue : M unit := +Definition callvalue (evm : Evm) : M unit := (* Push the value (in wei) sent with the call onto the stack. @@ -134,18 +156,22 @@ Definition callvalue : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["message"].["value"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition calldataload (evm : Evm) : M unit := (* Push a word (32 bytes) of the input data belonging to the current environment onto the stack. @@ -156,30 +182,38 @@ Definition calldataload : M unit := The current EVM frame. *) - let* start_index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - start_index, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] 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* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - value + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 |) - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition calldatasize : M unit := +Definition calldatasize (evm : Evm) : M unit := (* Push the size of input data in current environment onto the stack. @@ -190,22 +224,26 @@ Definition calldatasize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["message"].["data"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition calldatacopy : M unit := +Definition calldatacopy (evm : Evm) : M unit := (* Copy a portion of the input data in current environment to memory. @@ -218,40 +256,60 @@ Definition calldatacopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* data_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - data_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition codesize (evm : Evm) : M unit := (* Push the size of code running in current environment onto the stack. @@ -262,22 +320,26 @@ Definition codesize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["code"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition codecopy : M unit := +Definition codecopy (evm : Evm) : M unit := (* Copy a portion of the code in current environment to memory. @@ -290,40 +352,60 @@ Definition codecopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["code"], - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition gasprice (evm : Evm) : M unit := (* Push the gas price used in current environment onto the stack. @@ -334,20 +416,24 @@ Definition gasprice : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_price"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition extcodesize : M unit := +Definition extcodesize (evm : Evm) : M unit := (* Push the code size of a given account onto the stack. @@ -357,28 +443,36 @@ Definition extcodesize : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - (* TODO statement *) - let* codesize := ethereum_types.numeric.U256 (| - len (| - state.get_account (| - evm.["env"].["state"], - address - |).["code"] + 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 - do* stack.push (| - evm.["stack"], - codesize - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition extcodecopy : M unit := +Definition extcodecopy (evm : Evm) : M unit := (* Copy a portion of an account's code to memory. @@ -388,46 +482,70 @@ Definition extcodecopy : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - (* TODO statement *) - let* code := state.get_account (| - evm.["env"].["state"], - address - |).["code"] in - let* value := vm.memory.buffer_read (| - code, - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in + 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 : M unit := +Definition returndatasize (evm : Evm) : M unit := (* Pushes the size of the return data buffer onto the stack. @@ -437,22 +555,26 @@ Definition returndatasize : M unit := The current EVM frame. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["return_data"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition returndatacopy : M unit := +Definition returndatacopy (evm : Evm) : M unit := (* Copies data from the return data buffer code to memory @@ -461,37 +583,57 @@ Definition returndatacopy : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* return_data_start_position := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - (* TODO statement *) - let* value := (* TODO expression *) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in + |) ]] 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 : M unit := +Definition extcodehash (evm : Evm) : M unit := (* Returns the keccak256 hash of a contract’s bytecode Parameters @@ -499,25 +641,33 @@ Definition extcodehash : M unit := evm : The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] + 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 - (* TODO statement *) - let* account := state.get_account (| - evm.["env"].["state"], - address - |) in - (* TODO statement *) - do* stack.push (| - evm.["stack"], - codehash - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition self_balance : M unit := +Definition self_balance (evm : Evm) : M unit := (* Pushes the balance of the current address to the stack. @@ -528,17 +678,23 @@ Definition self_balance : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_FAST_STEP - |) in - let* balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/berlin/vm/instructions/keccak.v index aeef55db2c..cd511b7d44 100644 --- a/coq/ethereum/berlin/vm/instructions/keccak.v +++ b/coq/ethereum/berlin/vm/instructions/keccak.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Keccak Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM keccak instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require berlin.vm.gas. -Require berlin.vm.memory. -Require berlin.vm.stack. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.memory. +Require ethereum.berlin.vm.stack. -Definition keccak : M unit := +Definition keccak (evm : Evm) : M unit := (* Pushes to the stack the Keccak-256 hash of a region of memory. @@ -32,36 +34,56 @@ Definition keccak : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* word_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in - let* hash := ethereum.crypto.hash.keccak256 (| - data - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/berlin/vm/instructions/log.v index 8183fbf41c..6726133595 100644 --- a/coq/ethereum/berlin/vm/instructions/log.v +++ b/coq/ethereum/berlin/vm/instructions/log.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Logging Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,13 +15,14 @@ Implementations of the EVM logging instructions. Require functools. Require ethereum_types.numeric. -Require berlin.blocks. -Require berlin.vm.exceptions. -Require berlin.vm.gas. -Require berlin.vm.memory. -Require berlin.vm.stack. +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 : M unit := +Definition log_n (evm : Evm) (num_topics : U256) : M unit := (* Appends a log entry, having `num_topics` topics, to the evm logs. @@ -35,27 +37,43 @@ Definition log_n : M unit := The number of topics to be included in the log entry. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* topics := (* TODO expression *) in + 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 *) - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in (* TODO statement *) - let* log_entry := blocks.Log (| + do* M.assign "log_entry" [[ + blocks.Log ~(| - |) in + |) in + ]] in (* TODO assignment *) - (* 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/memory.v b/coq/ethereum/berlin/vm/instructions/memory.v index 1af3aa3a10..a06afeeafb 100644 --- a/coq/ethereum/berlin/vm/instructions/memory.v +++ b/coq/ethereum/berlin/vm/instructions/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM Memory instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require berlin.vm.gas. -Require berlin.vm.memory. -Require berlin.vm.stack. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.memory. +Require ethereum.berlin.vm.stack. -Definition mstore : M unit := +Definition mstore (evm : Evm) : M unit := (* Stores a word to memory. This also expands the memory, if the memory is @@ -30,32 +32,44 @@ Definition mstore : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* memory.memory_write (| - evm.["memory"], - start_position, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mstore8 (evm : Evm) : M unit := (* Stores a byte to memory. This also expands the memory, if the memory is @@ -67,33 +81,47 @@ Definition mstore8 : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ (* TODO expression *) - |) in - do* memory.memory_write (| - evm.["memory"], - start_position, - normalized_bytes_value - |) in - (* TODO statement *) - + ]] 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 : M unit := +Definition mload (evm : Evm) : M unit := (* Load word from memory. @@ -103,35 +131,47 @@ Definition mload : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.memory_read_bytes (| - evm.["memory"], - start_position, - ethereum_types.numeric.U256 (| - (* 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 - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition msize : M unit := +Definition msize (evm : Evm) : M unit := (* Push the size of active memory in bytes onto the stack. @@ -142,17 +182,21 @@ Definition msize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["memory"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/berlin/vm/instructions/stack.v index 8b1ac68678..ad3f28a6bd 100644 --- a/coq/ethereum/berlin/vm/instructions/stack.v +++ b/coq/ethereum/berlin/vm/instructions/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM stack related instructions. Require functools. Require ethereum_types.numeric. -Require berlin.vm.exceptions. -Require berlin.vm.gas. -Require berlin.vm.memory. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.exceptions. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.memory. -Definition pop : M unit := +Definition pop (evm : Evm) : M unit := (* Remove item from stack. @@ -28,18 +30,22 @@ Definition pop : M unit := The current EVM frame. *) - do* stack.["pop"] (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in + |) ]] in (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition push_n : M unit := +Definition push_n (evm : Evm) (num_bytes : int) : M unit := (* Pushes a N-byte immediate onto the stack. @@ -54,29 +60,33 @@ Definition push_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - evm.["code"], - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - num_bytes + |) ]] 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 - do* stack.["push"] (| - evm.["stack"], - data_to_push - |) in - (* TODO statement *) - - -Definition dup_n : M unit := + |) 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. @@ -91,20 +101,26 @@ Definition dup_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - let* data_to_duplicate := (* TODO expression *) in - do* stack.["push"] (| - evm.["stack"], - data_to_duplicate - |) 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 : M unit := +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. @@ -123,11 +139,15 @@ Definition swap_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - (* 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/storage.v b/coq/ethereum/berlin/vm/instructions/storage.v index cea8a2837c..753df96ca4 100644 --- a/coq/ethereum/berlin/vm/instructions/storage.v +++ b/coq/ethereum/berlin/vm/instructions/storage.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Storage Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,12 +14,13 @@ Implementations of the EVM storage related instructions. *) Require ethereum_types.numeric. -Require berlin.state. -Require berlin.vm.exceptions. -Require berlin.vm.gas. -Require berlin.vm.stack. +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 : M unit := +Definition sload (evm : Evm) : M unit := (* Loads to the stack, the value corresponding to a certain key from the storage of the current account. @@ -29,25 +31,33 @@ Definition sload : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in + |) in + ]] in (* TODO statement *) - let* value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) 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 : M unit := +Definition sstore (evm : Evm) : M unit := (* Stores a value at a certain key in the current context's storage. @@ -57,41 +67,55 @@ Definition sstore : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in (* TODO statement *) - let* original_value := state.get_storage_original (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - let* current_value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - let* gas_cost := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in + M.get_local ~(| "gas_cost" |) + |) ]] in (* TODO statement *) - do* state.set_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key, - new_value - |) 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.v b/coq/ethereum/berlin/vm/instructions/system.v index 5b11f67828..273ded3dc3 100644 --- a/coq/ethereum/berlin/vm/instructions/system.v +++ b/coq/ethereum/berlin/vm/instructions/system.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) System Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,57 +16,72 @@ Implementations of the EVM system related instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require berlin.fork_types. -Require berlin.state. -Require berlin.utils.address. -Require berlin.vm.exceptions. -Require berlin.vm.gas. -Require berlin.vm.memory. -Require berlin.vm.stack. - -Definition generic_create : M unit := +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* evm.["accessed_addresses"].["add"] (| + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "add" |) ~(| contract_address - |) in - let* create_message_gas := gas.max_message_call_gas (| - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |) - |) in - (* TODO statement *) + |) ]] 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 *) - let* sender_address := evm.["message"].["current_target"] in - let* sender := state.get_account (| - evm.["env"].["state"], - sender_address - |) in - (* TODO statement *) - (* TODO statement *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) in - do* state.increment_nonce (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |) in - let* child_message := Message (| - - |) in - let* child_evm := process_create_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - - -Definition create : M unit := + 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. @@ -74,42 +90,58 @@ Definition create : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_contract_address (| - evm.["message"].["current_target"], - state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["nonce"] - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition create2 (evm : Evm) : M unit := (* Creates a new account with associated code. @@ -121,50 +153,70 @@ Definition create2 : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* salt := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* call_data_words := (* TODO expression *) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_create2_contract_address (| - evm.["message"].["current_target"], - salt, - memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size - |) in - (* TODO statement *) - + 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_ : M unit := +Definition return_ (evm : Evm) : M unit := (* Halts execution returning output data. @@ -173,66 +225,84 @@ Definition return_ : M unit := evm : The current EVM frame. *) - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) + |) ]] 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 : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_input_start_position, - memory_input_size - |) in - let* code := state.get_account (| - evm.["env"].["state"], - code_address - |).["code"] in - let* child_message := Message (| - - |) in - let* child_evm := process_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - let* actual_output_size := min (| - memory_output_size, - ethereum_types.numeric.U256 (| - len (| - child_evm.["output"] + 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 - do* memory.memory_write (| - evm.["memory"], + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), memory_output_start_position, (* TODO expression *) - |) in + |) ]] in + M.pure tt. - -Definition call : M unit := +Definition call (evm : Evm) : M unit := (* Message-call into an account. @@ -241,62 +311,92 @@ Definition call : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* create_gas_cost := (* TODO expression *) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition callcode (evm : Evm) : M unit := (* Message-call into this account with alternative account’s code. @@ -305,61 +405,91 @@ Definition callcode : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* to := evm.["message"].["current_target"] in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) - (* TODO statement *) - + |) ]] 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 : M unit := +Definition selfdestruct (evm : Evm) : M unit := (* Halt execution and register account for later deletion. @@ -368,53 +498,67 @@ Definition selfdestruct : M unit := evm : The current EVM frame. *) - let* beneficiary := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* gas_cost := gas.GAS_SELF_DESTRUCT in + 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 *) - let* originator := evm.["message"].["current_target"] in - let* refunded_accounts := evm.["accounts_to_delete"] in - let* parent_evm := evm.["message"].["parent_evm"] 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - (* TODO statement *) - let* beneficiary_balance := state.get_account (| - evm.["env"].["state"], - beneficiary - |).["balance"] in - let* originator_balance := state.get_account (| - evm.["env"].["state"], - originator - |).["balance"] in - do* state.set_account_balance (| - evm.["env"].["state"], - beneficiary, + 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 (| - evm.["env"].["state"], - originator, - ethereum_types.numeric.U256 (| - (* 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* evm.["accounts_to_delete"].["add"] (| - originator - |) in + |) ]] 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 : M unit := +Definition delegatecall (evm : Evm) : M unit := (* Message-call into an account. @@ -423,67 +567,89 @@ Definition delegatecall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - access_gas_cost - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - evm.["message"].["value"], - evm.["message"].["caller"], - evm.["message"].["current_target"], - code_address, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition staticcall (evm : Evm) : M unit := (* Message-call into an account. @@ -492,69 +658,91 @@ Definition staticcall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - access_gas_cost - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - ethereum_types.numeric.U256 (| - (* TODO expression *) + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 |), - evm.["message"].["current_target"], - to, - to, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +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 @@ -563,27 +751,37 @@ Definition revert : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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, - extend_memory.["cost"] - |) in - (* TODO statement *) - let* output := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in + 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.v b/coq/ethereum/berlin/vm/interpreter.v index 19315318ab..1e58adada8 100644 --- a/coq/ethereum/berlin/vm/interpreter.v +++ b/coq/ethereum/berlin/vm/interpreter.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Interpreter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +18,18 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.trace. -Require berlin.blocks. -Require berlin.fork_types. -Require berlin.state. -Require berlin.vm. -Require berlin.vm.gas. -Require berlin.vm.precompiled_contracts.mapping. -Require berlin.vm.exceptions. -Require berlin.vm.instructions. -Require berlin.vm.runtime. - -Definition process_message_call : M unit := +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`. @@ -47,19 +49,21 @@ Definition process_message_call : M unit := *) (* TODO statement *) (* TODO statement *) - let* tx_end := ethereum.trace.TransactionEnd (| - (* TODO expression *), - evm.["output"], - evm.["error"] - |) in - do* ethereum.trace.evm_trace (| - evm, - tx_end - |) in + 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 : M unit := +Definition process_create_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -75,30 +79,32 @@ Definition process_create_message : M unit := evm: :py:class:`~ethereum.berlin.vm.Evm` Items containing execution specific objects. *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.destroy_storage (| - env.["state"], - message.["current_target"] - |) in - do* state.mark_account_created (| - env.["state"], - message.["current_target"] - |) in - do* state.increment_nonce (| - env.["state"], - message.["current_target"] - |) in - let* evm := process_message (| - message, - env - |) in + 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 : M unit := +Definition process_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -115,23 +121,25 @@ Definition process_message : M unit := Items containing execution specific objects *) (* TODO statement *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.touch_account (| - env.["state"], - message.["current_target"] - |) in + 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 *) - let* evm := execute_code (| - message, - env - |) in + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition execute_code : M unit := +Definition execute_code (message : Message) (env : Environment) : M Evm := (* Executes bytecode present in the `message`. @@ -147,13 +155,19 @@ Definition execute_code : M unit := evm: `ethereum.vm.EVM` Items containing execution specific objects *) - let* code := message.["code"] in - let* valid_jump_destinations := runtime.get_valid_jump_destinations (| - code - |) in - let* evm := Evm (| - - |) in + 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.v b/coq/ethereum/berlin/vm/memory.v index 94b6a44639..88b516318f 100644 --- a/coq/ethereum/berlin/vm/memory.v +++ b/coq/ethereum/berlin/vm/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.byte. -Definition memory_write : M unit := +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := (* Writes to memory. @@ -30,9 +31,9 @@ Definition memory_write : M unit := Data to write to memory. *) (* TODO assignment *) + M.pure tt. - -Definition memory_read_bytes : M unit := +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := (* Read bytes from memory. @@ -51,9 +52,9 @@ Definition memory_read_bytes : M unit := Data read from memory. *) (* TODO statement *) + M.pure tt. - -Definition buffer_read : M unit := +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := (* Read bytes from a buffer. Padding with zeros if necessary. @@ -72,4 +73,4 @@ Definition buffer_read : M unit := Data read from memory. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/__init__.v b/coq/ethereum/berlin/vm/precompiled_contracts/__init__.v index c6802d7c7e..693661609c 100644 --- a/coq/ethereum/berlin/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/berlin/vm/precompiled_contracts/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,4 +14,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require berlin.utils.hexadecimal. +Require ethereum.berlin.utils.hexadecimal. diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/berlin/vm/precompiled_contracts/alt_bn128.v index b1a1019a08..15ae619b27 100644 --- a/coq/ethereum/berlin/vm/precompiled_contracts/alt_bn128.v +++ b/coq/ethereum/berlin/vm/precompiled_contracts/alt_bn128.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,12 +15,12 @@ Implementation of the ALT_BN128 precompiled contracts. Require ethereum_types.numeric. Require ethereum.crypto.alt_bn128. -Require berlin.vm. -Require berlin.vm.gas. -Require berlin.vm.memory. -Require berlin.vm.exceptions. +Require ethereum.berlin.vm. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.memory. +Require ethereum.berlin.vm.exceptions. -Definition alt_bn128_add : M unit := +Definition alt_bn128_add (evm : Evm) : M unit := (* The ALT_BN128 addition precompiled contract. @@ -28,76 +29,96 @@ Definition alt_bn128_add : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* x1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x1_bytes - |) - |) in - let* y1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y1_bytes - |) - |) in + 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 *) - let* p := (* TODO expression *) in + do* M.assign "p" [[ + (* TODO expression *) in + ]] in (* TODO assignment *) + M.pure tt. - -Definition alt_bn128_mul : M unit := +Definition alt_bn128_mul (evm : Evm) : M unit := (* The ALT_BN128 multiplication precompiled contract. @@ -106,63 +127,77 @@ Definition alt_bn128_mul : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* n := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) (* TODO statement *) - let* p := p0.["mul_by"] (| - n - |) in + 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 : M unit := +Definition alt_bn128_pairing_check (evm : Evm) : M unit := (* The ALT_BN128 pairing check precompiled contract. @@ -171,17 +206,21 @@ Definition alt_bn128_pairing_check : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 (| + ethereum_types.numeric.Uint ~(| (* TODO expression *) |) - |) in + |) ]] in (* TODO statement *) - let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/berlin/vm/precompiled_contracts/blake2f.v index a50ae00501..ac2f5936a2 100644 --- a/coq/ethereum/berlin/vm/precompiled_contracts/blake2f.v +++ b/coq/ethereum/berlin/vm/precompiled_contracts/blake2f.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,11 @@ Implementation of the `Blake2` precompiled contract. *) Require ethereum.crypto.blake2. -Require berlin.vm. -Require berlin.vm.gas. -Require berlin.vm.exceptions. +Require ethereum.berlin.vm. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.exceptions. -Definition blake2f : M unit := +Definition blake2f (evm : Evm) : M unit := (* Writes the Blake2 hash to output. @@ -26,16 +27,20 @@ Definition blake2f : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in (* TODO statement *) - let* blake2b := ethereum.crypto.blake2.Blake2b (| + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| - |) in + |) in + ]] in (* TODO assignment *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, (* TODO expression *) - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/berlin/vm/precompiled_contracts/ecrecover.v index 587da7fc61..cadaeda618 100644 --- a/coq/ethereum/berlin/vm/precompiled_contracts/ecrecover.v +++ b/coq/ethereum/berlin/vm/precompiled_contracts/ecrecover.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,11 +17,11 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require berlin.vm. -Require berlin.vm.gas. -Require berlin.vm.memory. +Require ethereum.berlin.vm. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.memory. -Definition ecrecover : M unit := +Definition ecrecover (evm : Evm) : M unit := (* Decrypts the address using elliptic curve DSA recovery mechanism and writes the address to output. @@ -30,64 +31,80 @@ Definition ecrecover : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* message_hash_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* message_hash := ethereum.crypto.hash.Hash32 (| - message_hash_bytes - |) in - let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + ethereum_types.numeric.U256 ~(| + 32 |) - |) - |) in - let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 + ]] 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 *) - let* address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/berlin/vm/precompiled_contracts/identity.v index 108e609b22..ae81e0d581 100644 --- a/coq/ethereum/berlin/vm/precompiled_contracts/identity.v +++ b/coq/ethereum/berlin/vm/precompiled_contracts/identity.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,10 @@ Implementation of the `IDENTITY` precompiled contract. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require berlin.vm. -Require berlin.vm.gas. +Require ethereum.berlin.vm. +Require ethereum.berlin.vm.gas. -Definition identity : M unit := +Definition identity (evm : Evm) : M unit := (* Writes the message data to output. @@ -26,11 +27,15 @@ Definition identity : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/mapping.v b/coq/ethereum/berlin/vm/precompiled_contracts/mapping.v index e1a6f7a35e..e296eda824 100644 --- a/coq/ethereum/berlin/vm/precompiled_contracts/mapping.v +++ b/coq/ethereum/berlin/vm/precompiled_contracts/mapping.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Mapping of precompiled contracts their implementations. *) Require typing. -Require berlin.fork_types. -Require berlin.vm.precompiled_contracts.alt_bn128. -Require berlin.vm.precompiled_contracts.blake2f. -Require berlin.vm.precompiled_contracts.ecrecover. -Require berlin.vm.precompiled_contracts.identity. -Require berlin.vm.precompiled_contracts.modexp. -Require berlin.vm.precompiled_contracts.ripemd160. -Require berlin.vm.precompiled_contracts.sha256. +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.v b/coq/ethereum/berlin/vm/precompiled_contracts/modexp.v index a3d758ba3a..760522f59c 100644 --- a/coq/ethereum/berlin/vm/precompiled_contracts/modexp.v +++ b/coq/ethereum/berlin/vm/precompiled_contracts/modexp.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,100 +15,120 @@ Implementation of the `MODEXP` precompiled contract. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require berlin.vm. -Require berlin.vm.gas. -Require berlin.vm.memory. +Require ethereum.berlin.vm. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.memory. -Definition modexp : M unit := +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. *) - let* data := evm.["message"].["data"] in - let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) - |) in - let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 - let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* exp_start := (* TODO expression *) in - let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - min (| - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 |), - exp_length + ethereum_types.numeric.U256 ~(| + 32 + |) |) - |) - |) in - do* vm.gas.charge_gas (| + |) 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, - gas_cost (| - base_length, - modulus_length, - exp_length, - exp_head + 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 + |) ]] in (* TODO statement *) - let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - base_length - |) - |) in - let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - exp_length - |) - |) in - let* modulus_start := (* TODO expression *) in - let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - modulus_start, - modulus_length - |) - |) in + 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 : M unit := +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := (* Estimate the complexity of performing a modular exponentiation. @@ -126,19 +147,23 @@ Definition complexity : M unit := complexity : `Uint` Complexity of performing the operation. *) - let* max_length := max (| - ethereum_types.numeric.Uint (| - base_length - |), - ethereum_types.numeric.Uint (| - modulus_length - |) - |) in - let* words := (* TODO expression *) in + 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 : M unit := +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := (* Calculate the number of iterations required to perform a modular exponentiation. @@ -161,9 +186,9 @@ Definition iterations : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition gas_cost : M unit := +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. @@ -189,15 +214,23 @@ Definition gas_cost : M unit := gas_cost : `Uint` Gas required for performing the operation. *) - let* multiplication_complexity := complexity (| - base_length, - modulus_length - |) in - let* iteration_count := iterations (| - exponent_length, - exponent_head - |) in - let* cost := (* TODO expression *) in - (* TODO statement *) + 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.v b/coq/ethereum/berlin/vm/precompiled_contracts/ripemd160.v index bc5e73dd3c..fe2c66bbe6 100644 --- a/coq/ethereum/berlin/vm/precompiled_contracts/ripemd160.v +++ b/coq/ethereum/berlin/vm/precompiled_contracts/ripemd160.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `RIPEMD160` precompiled contract. *) -Definition ripemd160 : M unit := +Definition ripemd160 (evm : Evm) : M unit := (* Writes the ripemd160 hash to output. @@ -22,21 +23,29 @@ Definition ripemd160 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 - let* hash_bytes := hashlib.["new"] (| - (* TODO expression *), - data - |).["digest"] (| - - |) in - let* padded_hash := left_pad_zero_bytes (| - hash_bytes, - (* TODO expression *) - |) in + |) ]] 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.v b/coq/ethereum/berlin/vm/precompiled_contracts/sha256.v index da6972d411..3ba3ffe7aa 100644 --- a/coq/ethereum/berlin/vm/precompiled_contracts/sha256.v +++ b/coq/ethereum/berlin/vm/precompiled_contracts/sha256.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `SHA256` precompiled contract. *) -Definition sha256 : M unit := +Definition sha256 (evm : Evm) : M unit := (* Writes the sha256 hash to output. @@ -22,11 +23,15 @@ Definition sha256 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/berlin/vm/runtime.v b/coq/ethereum/berlin/vm/runtime.v index 818241a214..4553022893 100644 --- a/coq/ethereum/berlin/vm/runtime.v +++ b/coq/ethereum/berlin/vm/runtime.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Runtime Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Runtime related operations used while executing EVM code. Require typing. Require ethereum_types.numeric. -Require berlin.vm.instructions. +Require ethereum.berlin.vm.instructions. -Definition get_valid_jump_destinations : M unit := +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := (* Analyze the evm code to obtain the set of valid jump destinations. @@ -38,12 +39,16 @@ Definition get_valid_jump_destinations : M unit := valid_jump_destinations: `Set[Uint]` The set of valid jump destinations in the code. *) - let* valid_jump_destinations := set (| - - |) in - let* pc := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/berlin/vm/stack.v index 27ef379dba..e104e7225e 100644 --- a/coq/ethereum/berlin/vm/stack.v +++ b/coq/ethereum/berlin/vm/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Implementation of the stack operators for the EVM. Require typing. Require ethereum_types.numeric. -Require berlin.vm.exceptions. +Require ethereum.berlin.vm.exceptions. -Definition pop : M unit := +Definition pop (stack : (* TODO type *)) : M U256 := (* Pops the top item off of `stack`. @@ -33,9 +34,9 @@ Definition pop : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition push : M unit := +Definition push (stack : (* TODO type *)) (value : U256) : M unit := (* Pushes `value` onto `stack`. @@ -50,4 +51,4 @@ Definition push : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/byzantium/__init__.v b/coq/ethereum/byzantium/__init__.v index 14ce5a10a1..7d892ebede 100644 --- a/coq/ethereum/byzantium/__init__.v +++ b/coq/ethereum/byzantium/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* The Byzantium fork reduces the mining rewards, delays the difficulty bomb, lets contracts make non-state-changing calls to other contracts, and adds diff --git a/coq/ethereum/byzantium/blocks.v b/coq/ethereum/byzantium/blocks.v index 6c9a220f34..54b88d4b70 100644 --- a/coq/ethereum/byzantium/blocks.v +++ b/coq/ethereum/byzantium/blocks.v @@ -1,3 +1,4 @@ +(* 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 @@ -14,6 +15,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. -Require byzantium.fork_types. -Require byzantium.transactions. +Require ethereum.crypto.hash. +Require ethereum.byzantium.fork_types. +Require ethereum.byzantium.transactions. diff --git a/coq/ethereum/byzantium/bloom.v b/coq/ethereum/byzantium/bloom.v index 09494c0e11..93ebeb1829 100644 --- a/coq/ethereum/byzantium/bloom.v +++ b/coq/ethereum/byzantium/bloom.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Logs Bloom ^^^^^^^^^^^^^^^^^^^ @@ -19,10 +20,10 @@ eliminating blocks and receipts from their search. Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require byzantium.blocks. -Require byzantium.fork_types. +Require ethereum.byzantium.blocks. +Require ethereum.byzantium.fork_types. -Definition add_to_bloom : M unit := +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := (* Add a bloom entry to the bloom filter (`bloom`). @@ -37,13 +38,15 @@ Definition add_to_bloom : M unit := bloom_entry : An entry which is to be added to bloom filter. *) - let* hash := ethereum.crypto.hash.keccak256 (| - bloom_entry - |) in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition logs_bloom : M unit := +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := (* Obtain the logs bloom from a list of log entries. @@ -63,4 +66,4 @@ Definition logs_bloom : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/byzantium/fork.v b/coq/ethereum/byzantium/fork.v index ac9ee32443..8ddfd5df4d 100644 --- a/coq/ethereum/byzantium/fork.v +++ b/coq/ethereum/byzantium/fork.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^ @@ -20,16 +21,18 @@ Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.ethash. Require ethereum.exceptions. -Require byzantium.blocks. -Require byzantium.bloom. -Require byzantium.fork_types. -Require byzantium.state. -Require byzantium.transactions. -Require byzantium.trie. -Require byzantium.utils.message. -Require byzantium.vm.interpreter. - -Definition apply_fork : M unit := +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. @@ -49,9 +52,9 @@ Definition apply_fork : M unit := Upgraded block chain object for this hard fork. *) (* TODO statement *) + M.pure tt. - -Definition get_last_256_block_hashes : M unit := +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. @@ -71,22 +74,28 @@ Definition get_last_256_block_hashes : M unit := recent_block_hashes : `List[Hash32]` Hashes of the recent 256 blocks in order of increasing block number. *) - let* recent_blocks := (* TODO expression *) in - (* TODO statement *) - let* recent_block_hashes := (* TODO expression *) in - (* TODO statement *) - let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *).["header"] - |) - |) in - do* recent_block_hashes.["append"] (| - most_recent_block_hash - |) in - (* TODO statement *) - - -Definition state_transition : M unit := + 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. @@ -108,42 +117,46 @@ Definition state_transition : M unit := block : Block to apply to `chain`. *) - let* parent_header := (* TODO expression *).["header"] in - do* validate_header (| - block.["header"], - parent_header - |) in - do* validate_ommers (| - block.["ommers"], - block.["header"], + 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 - let* apply_body_output := apply_body (| - chain.["state"], - get_last_256_block_hashes (| - chain - |), - block.["header"].["coinbase"], - block.["header"].["number"], - block.["header"].["gas_limit"], - block.["header"].["timestamp"], - block.["header"].["difficulty"], - block.["transactions"], - block.["ommers"], - chain.["chain_id"] - |) in + |) ]] 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* chain.["blocks"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| block - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition validate_header : M unit := +Definition validate_header (header : Header) (parent_header : Header) : M unit := (* Verifies a block header. @@ -161,31 +174,37 @@ Definition validate_header : M unit := parent_header : Parent Header of the header to check for correctness *) - let* parent_has_ommers := (* TODO expression *) in + do* M.assign "parent_has_ommers" [[ + (* TODO expression *) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* block_difficulty := calculate_block_difficulty (| - header.["number"], - header.["timestamp"], - parent_header.["timestamp"], - parent_header.["difficulty"], - parent_has_ommers - |) in + 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 *) - let* block_parent_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - parent_header - |) - |) in + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in (* TODO statement *) - do* validate_proof_of_work (| + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| header - |) in - + |) ]] in + M.pure tt. -Definition generate_header_hash_for_pow : M unit := +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. @@ -208,11 +227,13 @@ Definition generate_header_hash_for_pow : M unit := hash : `Hash32` The PoW valid rlp hash of the passed in header. *) - let* header_data_without_pow_artefacts := (* TODO expression *) in + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition validate_proof_of_work : M unit := +Definition validate_proof_of_work (header : Header) : M unit := (* Validates the Proof of Work constraints. @@ -227,19 +248,25 @@ Definition validate_proof_of_work : M unit := header : Header of interest. *) - let* header_hash := generate_header_hash_for_pow (| - header - |) in - let* cache := ethereum.ethash.generate_cache (| - header.["number"] - |) in + 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 *) - let* limit := (* TODO expression *) in + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition check_transaction : M unit := +Definition check_transaction (tx : Transaction) (gas_available : Uint) (chain_id : U64) : M Address := (* Check if the transaction is includable in the block. @@ -263,14 +290,16 @@ Definition check_transaction : M unit := If the transaction is not includable. *) (* TODO statement *) - let* sender_address := recover_sender (| - chain_id, - tx - |) in + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition make_receipt : M unit := +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. @@ -291,13 +320,15 @@ Definition make_receipt : M unit := receipt : The receipt for the transaction. *) - let* receipt := blocks.Receipt (| + do* M.assign "receipt" [[ + blocks.Receipt ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition apply_body : M unit := +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. @@ -338,25 +369,31 @@ Definition apply_body : M unit := apply_body_output : `ApplyBodyOutput` Output of applying the block body to the state. *) - let* gas_available := block_gas_limit in + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - do* pay_rewards (| + do* [[ M.get_local ~(| "pay_rewards" |) ~(| state, block_number, coinbase, ommers - |) in - let* block_gas_used := (* TODO expression *) in - let* block_logs_bloom := bloom.logs_bloom (| - block_logs - |) in - (* TODO statement *) - - -Definition validate_ommers : M unit := + |) ]] 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. @@ -378,23 +415,31 @@ Definition validate_ommers : M unit := chain : History and current state. *) - let* block_hash := rlp.["rlp_hash"] (| - block_header - |) in + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* ommers_hashes := (* TODO expression *) in + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* recent_canonical_blocks := (* TODO expression *) in - let* recent_canonical_block_hashes := (* TODO expression *) in + 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 : M unit := +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. @@ -420,21 +465,25 @@ Definition pay_rewards : M unit := ommers : List of ommers mentioned in the current block. *) - let* ommer_count := ethereum_types.numeric.U256 (| - len (| - ommers - |) - |) in - let* miner_reward := (* TODO expression *) in - do* state.create_ether (| + 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, - miner_reward - |) in + M.get_local ~(| "miner_reward" |) + |) ]] in (* TODO statement *) + M.pure tt. - -Definition process_transaction : M unit := +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := (* Execute a transaction against the provided environment. @@ -462,64 +511,92 @@ Definition process_transaction : M unit := Logs generated during execution. *) (* TODO statement *) - let* sender := env.["origin"] in - let* sender_account := state.get_account (| - env.["state"], - sender - |) in - let* gas_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* gas := (* TODO expression *) in - do* state.increment_nonce (| - env.["state"], - sender - |) in - let* sender_balance_after_gas_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - ethereum_types.numeric.U256 (| - sender_balance_after_gas_fee - |) - |) in - let* message := utils.message.prepare_message (| - sender, - tx.["to"], - tx.["value"], - tx.["data"], - gas, - env - |) in - let* output := vm.interpreter.process_message_call (| - message, - env - |) in - let* gas_used := (* TODO expression *) in - let* gas_refund := min (| - (* TODO expression *), - ethereum_types.numeric.Uint (| - output.["refund_counter"] + 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 - let* gas_refund_amount := (* TODO expression *) in - let* transaction_fee := (* TODO expression *) in - let* total_gas_used := (* TODO expression *) in - let* sender_balance_after_refund := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - sender_balance_after_refund - |) in - let* coinbase_balance_after_mining_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - - -Definition validate_transaction : M unit := + |) ]] 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. @@ -547,9 +624,9 @@ Definition validate_transaction : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition calculate_intrinsic_cost : M unit := +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := (* Calculates the gas that is charged before execution is started. @@ -572,13 +649,15 @@ Definition calculate_intrinsic_cost : M unit := verified : `ethereum.base_types.Uint` The intrinsic cost of the transaction. *) - let* data_cost := (* TODO expression *) in + do* M.assign "data_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition recover_sender : M unit := +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := (* Extracts the sender address from a transaction. @@ -605,9 +684,9 @@ Definition recover_sender : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_pre155 : M unit := +Definition signing_hash_pre155 (tx : Transaction) : M Hash32 := (* Compute the hash of a transaction used in a legacy (pre EIP 155) signature. @@ -622,9 +701,9 @@ Definition signing_hash_pre155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_155 : M unit := +Definition signing_hash_155 (tx : Transaction) (chain_id : U64) : M Hash32 := (* Compute the hash of a transaction used in a EIP 155 signature. @@ -641,9 +720,9 @@ Definition signing_hash_155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition compute_header_hash : M unit := +Definition compute_header_hash (header : Header) : M Hash32 := (* Computes the hash of a block header. @@ -676,9 +755,9 @@ Definition compute_header_hash : M unit := Hash of the header. *) (* TODO statement *) + M.pure tt. - -Definition check_gas_limit : M unit := +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := (* Validates the gas limit for a block. @@ -706,14 +785,16 @@ Definition check_gas_limit : M unit := check : `bool` True if gas limit constraints are satisfied, False otherwise. *) - let* max_adjustment_delta := (* TODO expression *) in + 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 : M unit := +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. @@ -752,9 +833,15 @@ Definition calculate_block_difficulty : M unit := difficulty : `ethereum.base_types.Uint` Computed difficulty for a block. *) - let* offset := (* TODO expression *) in - let* difficulty := (* TODO expression *) in - let* num_bomb_periods := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - + 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.v b/coq/ethereum/byzantium/fork_types.v index 14de99d5e5..d84cffdf45 100644 --- a/coq/ethereum/byzantium/fork_types.v +++ b/coq/ethereum/byzantium/fork_types.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Types ^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. +Require ethereum.__init__. +Require ethereum.crypto.hash. -Definition encode_account : M unit := +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := (* Encode `Account` dataclass. @@ -26,4 +28,4 @@ Definition encode_account : M unit := encoded without providing a storage root. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/byzantium/state.v b/coq/ethereum/byzantium/state.v index e96991d31a..79b91b8917 100644 --- a/coq/ethereum/byzantium/state.v +++ b/coq/ethereum/byzantium/state.v @@ -1,3 +1,4 @@ +(* Generated *) (* State ^^^^^ @@ -22,10 +23,10 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require byzantium.fork_types. -Require byzantium.trie. +Require ethereum.byzantium.fork_types. +Require ethereum.byzantium.trie. -Definition close_state : M unit := +Definition close_state (state : State) : M unit := (* Free resources held by the state. Used by optimized implementations to release file descriptors. @@ -33,9 +34,9 @@ Definition close_state : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition begin_transaction : M unit := +Definition begin_transaction (state : State) : M unit := (* Start a state transaction. @@ -47,12 +48,12 @@ Definition begin_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition commit_transaction : M unit := +Definition commit_transaction (state : State) : M unit := (* Commit a state transaction. @@ -61,12 +62,12 @@ Definition commit_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["pop"] (| - - |) in + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + |) ]] in + M.pure tt. -Definition rollback_transaction : M unit := +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. @@ -77,9 +78,9 @@ Definition rollback_transaction : M unit := The state. *) (* TODO assignment *) + M.pure tt. - -Definition get_account : M unit := +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. @@ -99,14 +100,16 @@ Definition get_account : M unit := account : `Account` Account at address. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition get_account_optional : M unit := +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. @@ -123,14 +126,16 @@ Definition get_account_optional : M unit := account : `Account` Account at address. *) - let* account := trie.trie_get (| - state.["_main_trie"], - address - |) in + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition set_account : M unit := +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()`). @@ -144,14 +149,14 @@ Definition set_account : M unit := account : `Account` Account to set at address. *) - do* trie.trie_set (| - state.["_main_trie"], + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), address, account - |) in - + |) ]] in + M.pure tt. -Definition destroy_account : M unit := +Definition destroy_account (state : State) (address : Address) : M unit := (* Completely remove the account at `address` and all of its storage. @@ -166,18 +171,18 @@ Definition destroy_account : M unit := address : `Address` Address of account to destroy. *) - do* destroy_storage (| + do* [[ M.get_local ~(| "destroy_storage" |) ~(| state, address - |) in - do* set_account (| + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - (* TODO expression *) - |) in - + tt + |) ]] in + M.pure tt. -Definition destroy_storage : M unit := +Definition destroy_storage (state : State) (address : Address) : M unit := (* Completely remove the storage at `address`. @@ -189,9 +194,9 @@ Definition destroy_storage : M unit := Address of account whose storage is to be deleted. *) (* TODO statement *) + M.pure tt. - -Definition get_storage : M unit := +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. @@ -210,19 +215,23 @@ Definition get_storage : M unit := value : `U256` Value at the key. *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition set_storage : M unit := +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. @@ -239,19 +248,21 @@ Definition set_storage : M unit := Value to set at the key. *) (* TODO statement *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - do* trie.trie_set (| - trie, + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), key, value - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition storage_root : M unit := +Definition storage_root (state : State) (address : Address) : M Root := (* Calculate the storage root of an account. @@ -269,9 +280,9 @@ Definition storage_root : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition state_root : M unit := +Definition state_root (state : State) : M Root := (* Calculate the state root. @@ -288,9 +299,9 @@ Definition state_root : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition account_exists : M unit := +Definition account_exists (state : State) (address : Address) : M bool := (* Checks if an account exists in the state trie @@ -307,9 +318,9 @@ Definition account_exists : M unit := True if account exists in the state trie, False otherwise *) (* TODO statement *) + M.pure tt. - -Definition account_has_code_or_nonce : M unit := +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := (* Checks if an account has non zero nonce or non empty code @@ -326,14 +337,16 @@ Definition account_has_code_or_nonce : M unit := True if if an account has non zero nonce or non empty code, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_empty : M unit := +Definition is_account_empty (state : State) (address : Address) : M bool := (* Checks if an account has zero nonce, empty code and zero balance. @@ -350,14 +363,16 @@ Definition is_account_empty : M unit := True if if an account has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition account_exists_and_is_empty : M unit := +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. @@ -375,14 +390,16 @@ Definition account_exists_and_is_empty : M unit := True if an account exists and has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_alive : M unit := +Definition is_account_alive (state : State) (address : Address) : M bool := (* Check whether is an account is both in the state and non empty. @@ -398,49 +415,51 @@ Definition is_account_alive : M unit := is_alive : `bool` True if the account is alive. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition modify_state : M unit := +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := (* Modify an `Account` in the `State`. *) - do* set_account (| + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - ethereum_types.frozen.modify (| - get_account (| + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| state, address |), f |) - |) in - + |) ]] in + M.pure tt. -Definition move_ether : M unit := +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := (* Move funds between accounts. *) (* TODO statement *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, sender_address, - reduce_sender_balance - |) in - do* modify_state (| + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| state, recipient_address, - increase_recipient_balance - |) in + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. - -Definition set_account_balance : M unit := +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := (* Sets the balance of an account. @@ -456,14 +475,14 @@ Definition set_account_balance : M unit := The amount that needs to set in balance. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - set_balance - |) in - + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. -Definition touch_account : M unit := +Definition touch_account (state : State) (address : Address) : M unit := (* Initializes an account to state. @@ -476,9 +495,9 @@ Definition touch_account : M unit := The address of the account that need to initialised. *) (* TODO statement *) + M.pure tt. - -Definition increment_nonce : M unit := +Definition increment_nonce (state : State) (address : Address) : M unit := (* Increments the nonce of an account. @@ -491,14 +510,14 @@ Definition increment_nonce : M unit := Address of the account whose nonce needs to be incremented. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_nonce - |) in - + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. -Definition set_code : M unit := +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := (* Sets Account code. @@ -514,14 +533,14 @@ Definition set_code : M unit := The bytecode that needs to be set. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - write_code - |) in + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. - -Definition create_ether : M unit := +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := (* Add newly created ether to an account. @@ -535,9 +554,9 @@ Definition create_ether : M unit := The amount of ether to be added to the account of interest. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_balance - |) in - + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. diff --git a/coq/ethereum/byzantium/transactions.v b/coq/ethereum/byzantium/transactions.v index 37fb6cb470..d4c75cb9b0 100644 --- a/coq/ethereum/byzantium/transactions.v +++ b/coq/ethereum/byzantium/transactions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, @@ -9,4 +10,4 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require byzantium.fork_types. +Require ethereum.byzantium.fork_types. diff --git a/coq/ethereum/byzantium/trie.v b/coq/ethereum/byzantium/trie.v index 548de91e1c..6b8953f256 100644 --- a/coq/ethereum/byzantium/trie.v +++ b/coq/ethereum/byzantium/trie.v @@ -1,3 +1,4 @@ +(* Generated *) (* State Trie ^^^^^^^^^^ @@ -14,7 +15,7 @@ The state trie is the structure responsible for storing *) -Definition encode_internal_node : M unit := +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 @@ -35,22 +36,24 @@ Definition encode_internal_node : M unit := *) (* TODO statement *) (* TODO statement *) - let* encoded := rlp.["encode"] (| - unencoded - |) in + 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 : M unit := +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 : M unit := +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. @@ -66,9 +69,9 @@ Definition copy_trie : M unit := A copy of the trie. *) (* TODO statement *) + M.pure tt. - -Definition trie_set : M unit := +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := (* Stores an item in a Merkle Trie. @@ -85,9 +88,9 @@ Definition trie_set : M unit := Node to insert at `key`. *) (* TODO statement *) + M.pure tt. - -Definition trie_get : M unit := +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := (* Gets an item from the Merkle Trie. @@ -106,17 +109,17 @@ Definition trie_get : M unit := Node at `key` in the trie. *) (* TODO statement *) + M.pure tt. - -Definition common_prefix_length : M unit := +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 : M unit := +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := (* Compresses nibble-list into a standard byte array with a flag. @@ -150,14 +153,16 @@ Definition nibble_list_to_compact : M unit := compressed : `bytearray` Compact byte array. *) - let* compact := bytearray (| + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition bytes_to_nibble_list : M unit := +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := (* Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). @@ -171,14 +176,16 @@ Definition bytes_to_nibble_list : M unit := nibble_list : `Bytes` The `Bytes` in nibble-list format. *) - let* nibble_list := bytearray (| - (* TODO expression *) - |) in + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _prepare_trie : M unit := +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. @@ -199,9 +206,9 @@ Definition _prepare_trie : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition root : M unit := +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := (* Computes the root of a modified merkle patricia trie (MPT). @@ -219,22 +226,26 @@ Definition root : M unit := root : `.fork_types.Root` MPT root of the underlying key-value pairs. *) - let* obj := _prepare_trie (| - trie, - get_storage_root - |) in - let* root_node := encode_internal_node (| - patricialize (| - obj, - Uint (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) + M.pure tt. - -Definition patricialize : M unit := +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := (* Structural composition function. @@ -254,21 +265,29 @@ Definition patricialize : M unit := Root node of `obj`. *) (* TODO statement *) - let* arbitrary_key := next (| - iter (| - obj - |) - |) in + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in (* TODO statement *) - let* substring := (* TODO expression *) in - let* prefix_length := len (| - substring - |) in + 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 *) - let* value := (* TODO expression *) in + do* M.assign "value" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/byzantium/utils/__init__.v b/coq/ethereum/byzantium/utils/__init__.v index beff4482b1..7f30fe939b 100644 --- a/coq/ethereum/byzantium/utils/__init__.v +++ b/coq/ethereum/byzantium/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions unique to this particular fork. *) diff --git a/coq/ethereum/byzantium/utils/address.v b/coq/ethereum/byzantium/utils/address.v index 4ed0274673..2a6eedadd5 100644 --- a/coq/ethereum/byzantium/utils/address.v +++ b/coq/ethereum/byzantium/utils/address.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,9 +18,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require byzantium.fork_types. +Require ethereum.__init__. +Require ethereum.byzantium.fork_types. -Definition to_address : M unit := +Definition to_address (data : (* TODO type *)) : M Address := (* Convert a Uint or U256 value to a valid address (20 bytes). @@ -34,9 +36,9 @@ Definition to_address : M unit := The obtained address. *) (* TODO statement *) + M.pure tt. - -Definition compute_contract_address : M unit := +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := (* Computes address of the new account that needs to be created. @@ -53,15 +55,21 @@ Definition compute_contract_address : M unit := address: `ethereum.byzantium.fork_types.Address` The computed address of the new account. *) - let* computed_address := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *) - |) - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/byzantium/utils/hexadecimal.v index 3741d1ddf7..5e558aa0c5 100644 --- a/coq/ethereum/byzantium/utils/hexadecimal.v +++ b/coq/ethereum/byzantium/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Byzantium types. *) Require ethereum.utils.hexadecimal. -Require byzantium.fork_types. +Require ethereum.byzantium.fork_types. -Definition hex_to_root : M unit := +Definition hex_to_root (hex_string : str) : M Root := (* Convert hex string to trie root. @@ -31,9 +32,9 @@ Definition hex_to_root : M unit := Trie root obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bloom : M unit := +Definition hex_to_bloom (hex_string : str) : M Bloom := (* Convert hex string to bloom. @@ -48,9 +49,9 @@ Definition hex_to_bloom : M unit := Bloom obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_address : M unit := +Definition hex_to_address (hex_string : str) : M Address := (* Convert hex string to Address (20 bytes). @@ -65,4 +66,4 @@ Definition hex_to_address : M unit := The address obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/byzantium/utils/message.v b/coq/ethereum/byzantium/utils/message.v index 5e07003262..2bd42562f2 100644 --- a/coq/ethereum/byzantium/utils/message.v +++ b/coq/ethereum/byzantium/utils/message.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For The Message Data-structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,12 +17,12 @@ specification. Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require byzantium.fork_types. -Require byzantium.state. -Require byzantium.vm. -Require byzantium.utils.address. +Require ethereum.byzantium.fork_types. +Require ethereum.byzantium.state. +Require ethereum.byzantium.vm. +Require ethereum.byzantium.utils.address. -Definition prepare_message : M unit := +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. @@ -56,4 +57,4 @@ Definition prepare_message : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/__init__.v b/coq/ethereum/byzantium/vm/__init__.v index 5ce592e183..f946a758ce 100644 --- a/coq/ethereum/byzantium/vm/__init__.v +++ b/coq/ethereum/byzantium/vm/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,12 +19,12 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require byzantium.blocks. -Require byzantium.fork_types. -Require byzantium.state. -Require byzantium.vm.precompiled_contracts. +Require ethereum.byzantium.blocks. +Require ethereum.byzantium.fork_types. +Require ethereum.byzantium.state. +Require ethereum.byzantium.vm.precompiled_contracts. -Definition incorporate_child_on_success : M unit := +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of a successful `child_evm` into the parent `evm`. @@ -34,19 +35,25 @@ Definition incorporate_child_on_success : M unit := 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 *) - (* TODO statement *) - (* TODO statement *) - do* evm.["accounts_to_delete"].["update"] (| - child_evm.["accounts_to_delete"] - |) in - do* evm.["touched_accounts"].["update"] (| - child_evm.["touched_accounts"] - |) in - (* TODO statement *) + M.pure tt. - -Definition incorporate_child_on_error : M unit := +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. @@ -59,5 +66,7 @@ Definition incorporate_child_on_error : M unit := *) (* TODO statement *) (* 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.v b/coq/ethereum/byzantium/vm/exceptions.v index 1784494410..47e26555d5 100644 --- a/coq/ethereum/byzantium/vm/exceptions.v +++ b/coq/ethereum/byzantium/vm/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Exceptions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/byzantium/vm/gas.v b/coq/ethereum/byzantium/vm/gas.v index 75ae562094..05b1603559 100644 --- a/coq/ethereum/byzantium/vm/gas.v +++ b/coq/ethereum/byzantium/vm/gas.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Gas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,9 +18,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.trace. Require ethereum.utils.numeric. -Require byzantium.vm.exceptions. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.exceptions. -Definition charge_gas : M unit := +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := (* Subtracts `amount` from `evm.gas_left`. @@ -31,18 +33,18 @@ Definition charge_gas : M unit := The amount of gas the current operation requires. *) - do* ethereum.trace.evm_trace (| + do* [[ ethereum.trace.evm_trace ~(| evm, - ethereum.trace.GasAndRefund (| - int (| + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| amount |) |) - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_memory_gas_cost : M unit := +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, @@ -58,14 +60,22 @@ Definition calculate_memory_gas_cost : M unit := total_gas_cost : `ethereum.base_types.Uint` The gas cost for storing data in memory. *) - let* size_in_words := (* TODO expression *) in - let* linear_cost := (* TODO expression *) in - let* quadratic_cost := (* TODO expression *) in - let* total_gas_cost := (* TODO expression *) in + 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 : M unit := +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := (* Calculates the gas amount to extend memory @@ -81,22 +91,28 @@ Definition calculate_gas_extend_memory : M unit := ------- extend_memory: `ExtendMemory` *) - let* size_to_extend := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* to_be_paid := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* current_size := ethereum_types.numeric.Uint (| - len (| - memory - |) - |) in + 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 : M unit := +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. @@ -122,18 +138,22 @@ Definition calculate_message_call_gas : M unit := ------- message_call_gas: `MessageCallGas` *) - let* call_stipend := (* TODO expression *) in + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* gas := min (| - gas, - max_message_call_gas (| - (* TODO expression *) - |) - |) in + 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 : M unit := +Definition max_message_call_gas (gas : Uint) : M Uint := (* Calculates the maximum gas that is allowed for making a message call @@ -148,4 +168,4 @@ Definition max_message_call_gas : M unit := The maximum gas allowed for making the message-call. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/instructions/__init__.v b/coq/ethereum/byzantium/vm/instructions/__init__.v index b36b1ebfef..cbd7e7e63a 100644 --- a/coq/ethereum/byzantium/vm/instructions/__init__.v +++ b/coq/ethereum/byzantium/vm/instructions/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* EVM Instruction Encoding (Opcodes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/byzantium/vm/instructions/arithmetic.v b/coq/ethereum/byzantium/vm/instructions/arithmetic.v index 14f853a54b..58d1976d35 100644 --- a/coq/ethereum/byzantium/vm/instructions/arithmetic.v +++ b/coq/ethereum/byzantium/vm/instructions/arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,11 @@ Implementations of the EVM Arithmetic instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require byzantium.vm.gas. -Require byzantium.vm.stack. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.stack. -Definition add : M unit := +Definition add (evm : Evm) : M unit := (* Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -28,27 +30,37 @@ Definition add : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_add"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sub (evm : Evm) : M unit := (* Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -59,27 +71,37 @@ Definition sub : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_sub"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mul (evm : Evm) : M unit := (* Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -90,27 +112,37 @@ Definition mul : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_mul"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition div (evm : Evm) : M unit := (* Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -121,25 +153,33 @@ Definition div : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |) in - let* divisor := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - quotient - |) 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 : M unit := +Definition sdiv (evm : Evm) : M unit := (* Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -150,31 +190,39 @@ Definition sdiv : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* divisor := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - quotient + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mod : M unit := +Definition mod (evm : Evm) : M unit := (* Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -185,25 +233,33 @@ Definition mod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - remainder - |) in + |) ]] 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 : M unit := +Definition smod (evm : Evm) : M unit := (* Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -214,31 +270,39 @@ Definition smod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* y := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - remainder + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition addmod : M unit := +Definition addmod (evm : Evm) : M unit := (* Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -249,34 +313,44 @@ Definition addmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +Definition mulmod (evm : Evm) : M unit := (* Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -287,34 +361,44 @@ Definition mulmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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 : M unit := +Definition exp (evm : Evm) : M unit := (* Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -325,39 +409,53 @@ Definition exp : M unit := The current EVM frame. *) - let* base := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent_bits := exponent.["bit_length"] (| - - |) in - let* exponent_bytes := (* TODO expression *) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - pow (| - base, - exponent, - (* 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 - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition signextend : M unit := +Definition signextend (evm : Evm) : M unit := (* Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -368,20 +466,28 @@ Definition signextend : M unit := The current EVM frame. *) - let* byte_num := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/byzantium/vm/instructions/bitwise.v index 7b2cee4bce..56886af9f9 100644 --- a/coq/ethereum/byzantium/vm/instructions/bitwise.v +++ b/coq/ethereum/byzantium/vm/instructions/bitwise.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Bitwise Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM bitwise instructions. *) Require ethereum_types.numeric. -Require byzantium.vm.gas. -Require byzantium.vm.stack. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.stack. -Definition bitwise_and : M unit := +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. @@ -27,24 +29,32 @@ Definition bitwise_and : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_or : M unit := + |) ]] 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. @@ -55,24 +65,32 @@ Definition bitwise_or : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_xor : M unit := + |) ]] 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. @@ -83,24 +101,32 @@ Definition bitwise_xor : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_not : M unit := + |) ]] 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. @@ -111,21 +137,27 @@ Definition bitwise_not : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition get_byte : M unit := + |) ]] 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 @@ -137,20 +169,28 @@ Definition get_byte : M unit := The current EVM frame. *) - let* byte_index := stack.pop (| - evm.["stack"] - |) in - let* word := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/byzantium/vm/instructions/block.v index e5341af50b..86adb30702 100644 --- a/coq/ethereum/byzantium/vm/instructions/block.v +++ b/coq/ethereum/byzantium/vm/instructions/block.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Block Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM block instructions. *) Require ethereum_types.numeric. -Require byzantium.vm.gas. -Require byzantium.vm.stack. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.stack. -Definition block_hash : M unit := +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. @@ -27,27 +29,35 @@ Definition block_hash : M unit := The current EVM frame. *) - let* block_number := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* max_block_number := (* TODO expression *) in + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition coinbase : M unit := +Definition coinbase (evm : Evm) : M unit := (* Push the current block's beneficiary address (address of the block miner) onto the stack. @@ -62,20 +72,24 @@ Definition coinbase : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["coinbase"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition timestamp : M unit := +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. @@ -90,18 +104,22 @@ Definition timestamp : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["env"].["time"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition number (evm : Evm) : M unit := (* Push the current block's number onto the stack. @@ -115,20 +133,24 @@ Definition number : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["number"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition difficulty : M unit := +Definition difficulty (evm : Evm) : M unit := (* Push the current block's difficulty onto the stack. @@ -142,20 +164,24 @@ Definition difficulty : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["difficulty"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_limit : M unit := +Definition gas_limit (evm : Evm) : M unit := (* Push the current block's gas limit onto the stack. @@ -169,15 +195,19 @@ Definition gas_limit : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_limit"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/byzantium/vm/instructions/comparison.v index 51d912e7b5..d76949b421 100644 --- a/coq/ethereum/byzantium/vm/instructions/comparison.v +++ b/coq/ethereum/byzantium/vm/instructions/comparison.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Comparison Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM Comparison instructions. *) Require ethereum_types.numeric. -Require byzantium.vm.gas. -Require byzantium.vm.stack. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.stack. -Definition less_than : M unit := +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. @@ -27,27 +29,37 @@ Definition less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_less_than : M unit := + |) ]] 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. @@ -57,31 +69,41 @@ Definition signed_less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition greater_than : M unit := + |) ]] 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. @@ -92,27 +114,37 @@ Definition greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_greater_than : M unit := + |) ]] 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. @@ -122,31 +154,41 @@ Definition signed_greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition equal : M unit := + |) ]] 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. @@ -157,27 +199,37 @@ Definition equal : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition is_zero : M unit := + |) ]] 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. @@ -188,19 +240,27 @@ Definition is_zero : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/byzantium/vm/instructions/control_flow.v index 83f597f9a9..34e896a17a 100644 --- a/coq/ethereum/byzantium/vm/instructions/control_flow.v +++ b/coq/ethereum/byzantium/vm/instructions/control_flow.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Control Flow Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM control flow instructions. *) Require ethereum_types.numeric. -Require byzantium.vm.gas. -Require byzantium.vm.exceptions. -Require byzantium.vm.stack. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.exceptions. +Require ethereum.byzantium.vm.stack. -Definition stop : M unit := +Definition stop (evm : Evm) : M unit := (* Stop further execution of EVM code. @@ -29,10 +31,14 @@ Definition stop : M unit := (* TODO statement *) (* TODO statement *) (* TODO assignment *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jump : M unit := +Definition jump (evm : Evm) : M unit := (* Alter the program counter to the location specified by the top of the stack. @@ -43,20 +49,22 @@ Definition jump : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition jumpi : M unit := +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 @@ -68,23 +76,27 @@ Definition jumpi : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* conditional_value := stack.pop (| - evm.["stack"] - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition pc : M unit := +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. @@ -96,20 +108,24 @@ Definition pc : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["pc"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_left : M unit := +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. @@ -121,20 +137,24 @@ Definition gas_left : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["gas_left"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jumpdest : M unit := +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 @@ -147,10 +167,14 @@ Definition jumpdest : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_JUMPDEST - |) in - (* TODO statement *) + |) ]] 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.v b/coq/ethereum/byzantium/vm/instructions/environment.v index 86d17235a8..05d8a66949 100644 --- a/coq/ethereum/byzantium/vm/instructions/environment.v +++ b/coq/ethereum/byzantium/vm/instructions/environment.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,14 +15,15 @@ Implementations of the EVM environment related instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require byzantium.state. -Require byzantium.utils.address. -Require byzantium.vm.memory. -Require byzantium.vm.exceptions. -Require byzantium.vm.gas. -Require byzantium.vm.stack. - -Definition address : M unit := +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. @@ -32,20 +34,24 @@ Definition address : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["current_target"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition balance : M unit := +Definition balance (evm : Evm) : M unit := (* Pushes the balance of the given account onto the stack. @@ -55,27 +61,35 @@ Definition balance : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* balance := state.get_account (| - evm.["env"].["state"], - address - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +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. @@ -87,20 +101,24 @@ Definition origin : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["origin"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition caller : M unit := +Definition caller (evm : Evm) : M unit := (* Pushes the address of the caller onto the stack. @@ -111,20 +129,24 @@ Definition caller : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["caller"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition callvalue : M unit := +Definition callvalue (evm : Evm) : M unit := (* Push the value (in wei) sent with the call onto the stack. @@ -135,18 +157,22 @@ Definition callvalue : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["message"].["value"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition calldataload (evm : Evm) : M unit := (* Push a word (32 bytes) of the input data belonging to the current environment onto the stack. @@ -157,30 +183,38 @@ Definition calldataload : M unit := The current EVM frame. *) - let* start_index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - start_index, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] 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* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - value + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 |) - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition calldatasize : M unit := +Definition calldatasize (evm : Evm) : M unit := (* Push the size of input data in current environment onto the stack. @@ -191,22 +225,26 @@ Definition calldatasize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["message"].["data"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition calldatacopy : M unit := +Definition calldatacopy (evm : Evm) : M unit := (* Copy a portion of the input data in current environment to memory. @@ -219,40 +257,60 @@ Definition calldatacopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* data_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - data_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition codesize (evm : Evm) : M unit := (* Push the size of code running in current environment onto the stack. @@ -263,22 +321,26 @@ Definition codesize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["code"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition codecopy : M unit := +Definition codecopy (evm : Evm) : M unit := (* Copy a portion of the code in current environment to memory. @@ -291,40 +353,60 @@ Definition codecopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["code"], - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition gasprice (evm : Evm) : M unit := (* Push the gas price used in current environment onto the stack. @@ -335,20 +417,24 @@ Definition gasprice : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_price"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition extcodesize : M unit := +Definition extcodesize (evm : Evm) : M unit := (* Push the code size of a given account onto the stack. @@ -358,31 +444,39 @@ Definition extcodesize : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* codesize := ethereum_types.numeric.U256 (| - len (| - state.get_account (| - evm.["env"].["state"], - address - |).["code"] + |) ]] 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 - do* stack.push (| - evm.["stack"], - codesize - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition extcodecopy : M unit := +Definition extcodecopy (evm : Evm) : M unit := (* Copy a portion of an account's code to memory. @@ -392,49 +486,73 @@ Definition extcodecopy : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* code := state.get_account (| - evm.["env"].["state"], - address - |).["code"] in - let* value := vm.memory.buffer_read (| - code, - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition returndatasize (evm : Evm) : M unit := (* Pushes the size of the return data buffer onto the stack. @@ -444,22 +562,26 @@ Definition returndatasize : M unit := The current EVM frame. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["return_data"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition returndatacopy : M unit := +Definition returndatacopy (evm : Evm) : M unit := (* Copies data from the return data buffer code to memory @@ -468,32 +590,52 @@ Definition returndatacopy : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* return_data_start_position := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) + |) ]] in (* TODO statement *) - let* value := (* TODO expression *) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) 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.v b/coq/ethereum/byzantium/vm/instructions/keccak.v index aad67596bc..3e0dae599a 100644 --- a/coq/ethereum/byzantium/vm/instructions/keccak.v +++ b/coq/ethereum/byzantium/vm/instructions/keccak.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Keccak Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM keccak instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require byzantium.vm.gas. -Require byzantium.vm.memory. -Require byzantium.vm.stack. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.memory. +Require ethereum.byzantium.vm.stack. -Definition keccak : M unit := +Definition keccak (evm : Evm) : M unit := (* Pushes to the stack the Keccak-256 hash of a region of memory. @@ -32,36 +34,56 @@ Definition keccak : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* word_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in - let* hash := ethereum.crypto.hash.keccak256 (| - data - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/byzantium/vm/instructions/log.v index 9da3e01eaa..cf94ab12d7 100644 --- a/coq/ethereum/byzantium/vm/instructions/log.v +++ b/coq/ethereum/byzantium/vm/instructions/log.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Logging Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,13 +15,14 @@ Implementations of the EVM logging instructions. Require functools. Require ethereum_types.numeric. -Require byzantium.blocks. -Require byzantium.vm.exceptions. -Require byzantium.vm.gas. -Require byzantium.vm.memory. -Require byzantium.vm.stack. +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 : M unit := +Definition log_n (evm : Evm) (num_topics : U256) : M unit := (* Appends a log entry, having `num_topics` topics, to the evm logs. @@ -35,27 +37,43 @@ Definition log_n : M unit := The number of topics to be included in the log entry. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* topics := (* TODO expression *) in + 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 *) - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in (* TODO statement *) - let* log_entry := blocks.Log (| + do* M.assign "log_entry" [[ + blocks.Log ~(| - |) in + |) in + ]] in (* TODO assignment *) - (* 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/memory.v b/coq/ethereum/byzantium/vm/instructions/memory.v index c14815403a..e929c50d1d 100644 --- a/coq/ethereum/byzantium/vm/instructions/memory.v +++ b/coq/ethereum/byzantium/vm/instructions/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM Memory instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require byzantium.vm.gas. -Require byzantium.vm.memory. -Require byzantium.vm.stack. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.memory. +Require ethereum.byzantium.vm.stack. -Definition mstore : M unit := +Definition mstore (evm : Evm) : M unit := (* Stores a word to memory. This also expands the memory, if the memory is @@ -30,32 +32,44 @@ Definition mstore : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* memory.memory_write (| - evm.["memory"], - start_position, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mstore8 (evm : Evm) : M unit := (* Stores a byte to memory. This also expands the memory, if the memory is @@ -67,33 +81,47 @@ Definition mstore8 : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ (* TODO expression *) - |) in - do* memory.memory_write (| - evm.["memory"], - start_position, - normalized_bytes_value - |) in - (* TODO statement *) - + ]] 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 : M unit := +Definition mload (evm : Evm) : M unit := (* Load word from memory. @@ -103,35 +131,47 @@ Definition mload : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.memory_read_bytes (| - evm.["memory"], - start_position, - ethereum_types.numeric.U256 (| - (* 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 - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition msize : M unit := +Definition msize (evm : Evm) : M unit := (* Push the size of active memory in bytes onto the stack. @@ -142,17 +182,21 @@ Definition msize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["memory"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/byzantium/vm/instructions/stack.v index 38bb843610..461fe3f43d 100644 --- a/coq/ethereum/byzantium/vm/instructions/stack.v +++ b/coq/ethereum/byzantium/vm/instructions/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM stack related instructions. Require functools. Require ethereum_types.numeric. -Require byzantium.vm.exceptions. -Require byzantium.vm.gas. -Require byzantium.vm.memory. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.exceptions. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.memory. -Definition pop : M unit := +Definition pop (evm : Evm) : M unit := (* Remove item from stack. @@ -28,18 +30,22 @@ Definition pop : M unit := The current EVM frame. *) - do* stack.["pop"] (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in + |) ]] in (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition push_n : M unit := +Definition push_n (evm : Evm) (num_bytes : int) : M unit := (* Pushes a N-byte immediate onto the stack. @@ -54,29 +60,33 @@ Definition push_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - evm.["code"], - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - num_bytes + |) ]] 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 - do* stack.["push"] (| - evm.["stack"], - data_to_push - |) in - (* TODO statement *) - - -Definition dup_n : M unit := + |) 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. @@ -91,20 +101,26 @@ Definition dup_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - let* data_to_duplicate := (* TODO expression *) in - do* stack.["push"] (| - evm.["stack"], - data_to_duplicate - |) 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 : M unit := +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. @@ -123,11 +139,15 @@ Definition swap_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - (* 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/storage.v b/coq/ethereum/byzantium/vm/instructions/storage.v index 0ad464fe24..92a5d1c781 100644 --- a/coq/ethereum/byzantium/vm/instructions/storage.v +++ b/coq/ethereum/byzantium/vm/instructions/storage.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Storage Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,12 +14,13 @@ Implementations of the EVM storage related instructions. *) Require ethereum_types.numeric. -Require byzantium.state. -Require byzantium.vm.exceptions. -Require byzantium.vm.gas. -Require byzantium.vm.stack. +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 : M unit := +Definition sload (evm : Evm) : M unit := (* Loads to the stack, the value corresponding to a certain key from the storage of the current account. @@ -29,28 +31,36 @@ Definition sload : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_SLOAD - |) in - let* value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sstore (evm : Evm) : M unit := (* Stores a value at a certain key in the current context's storage. @@ -60,31 +70,41 @@ Definition sstore : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in - let* current_value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in + |) 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in + M.get_local ~(| "gas_cost" |) + |) ]] in (* TODO statement *) - do* state.set_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key, - new_value - |) 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.v b/coq/ethereum/byzantium/vm/instructions/system.v index 26d4c0fbb3..754ab4e94c 100644 --- a/coq/ethereum/byzantium/vm/instructions/system.v +++ b/coq/ethereum/byzantium/vm/instructions/system.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) System Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,15 +15,16 @@ Implementations of the EVM system related instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require byzantium.fork_types. -Require byzantium.state. -Require byzantium.utils.address. -Require byzantium.vm.exceptions. -Require byzantium.vm.gas. -Require byzantium.vm.memory. -Require byzantium.vm.stack. +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 : M unit := +Definition create (evm : Evm) : M unit := (* Creates a new account with associated code. @@ -32,49 +34,73 @@ Definition create : M unit := The current EVM frame. *) (* TODO statement *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - let* create_message_gas := gas.max_message_call_gas (| - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |) - |) in - (* TODO statement *) - (* TODO statement *) + |) ]] 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 *) - let* sender_address := evm.["message"].["current_target"] in - let* sender := state.get_account (| - evm.["env"].["state"], - sender_address - |) in - let* contract_address := utils.address.compute_contract_address (| - evm.["message"].["current_target"], - state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["nonce"] - |) in - (* TODO statement *) + 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_ : M unit := +Definition return_ (evm : Evm) : M unit := (* Halts execution returning output data. @@ -83,66 +109,84 @@ Definition return_ : M unit := evm : The current EVM frame. *) - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) + |) ]] 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 : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_input_start_position, - memory_input_size - |) in - let* code := state.get_account (| - evm.["env"].["state"], - code_address - |).["code"] in - let* child_message := Message (| + 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 - let* child_evm := process_message (| - child_message, - evm.["env"] - |) in + |) 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 *) - let* actual_output_size := min (| - memory_output_size, - ethereum_types.numeric.U256 (| - len (| - child_evm.["output"] + 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 - do* memory.memory_write (| - evm.["memory"], + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), memory_output_start_position, (* TODO expression *) - |) in + |) ]] in + M.pure tt. - -Definition call : M unit := +Definition call (evm : Evm) : M unit := (* Message-call into an account. @@ -151,61 +195,91 @@ Definition call : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* create_gas_cost := (* TODO expression *) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in + |) ]] 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 : M unit := +Definition callcode (evm : Evm) : M unit := (* Message-call into this account with alternative account’s code. @@ -214,60 +288,90 @@ Definition callcode : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* to := evm.["message"].["current_target"] in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition selfdestruct (evm : Evm) : M unit := (* Halt execution and register account for later deletion. @@ -276,52 +380,66 @@ Definition selfdestruct : M unit := evm : The current EVM frame. *) - let* beneficiary := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* gas_cost := gas.GAS_SELF_DESTRUCT in + 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 *) - let* originator := evm.["message"].["current_target"] in - let* refunded_accounts := evm.["accounts_to_delete"] in - let* parent_evm := evm.["message"].["parent_evm"] 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in + M.get_local ~(| "gas_cost" |) + |) ]] in (* TODO statement *) - let* beneficiary_balance := state.get_account (| - evm.["env"].["state"], - beneficiary - |).["balance"] in - let* originator_balance := state.get_account (| - evm.["env"].["state"], - originator - |).["balance"] in - do* state.set_account_balance (| - evm.["env"].["state"], - beneficiary, + 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 (| - evm.["env"].["state"], - originator, - ethereum_types.numeric.U256 (| - (* 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* evm.["accounts_to_delete"].["add"] (| - originator - |) in + |) ]] 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 : M unit := +Definition delegatecall (evm : Evm) : M unit := (* Message-call into an account. @@ -330,66 +448,88 @@ Definition delegatecall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - gas.GAS_CALL - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - evm.["message"].["value"], - evm.["message"].["caller"], - evm.["message"].["current_target"], - code_address, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition staticcall (evm : Evm) : M unit := (* Message-call into an account. @@ -398,68 +538,90 @@ Definition staticcall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - gas.GAS_CALL - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - ethereum_types.numeric.U256 (| - (* TODO expression *) + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 |), - evm.["message"].["current_target"], - to, - to, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +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 @@ -468,27 +630,37 @@ Definition revert : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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, - extend_memory.["cost"] - |) in - (* TODO statement *) - let* output := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in + 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.v b/coq/ethereum/byzantium/vm/interpreter.v index 498c7ea8cf..20015c237b 100644 --- a/coq/ethereum/byzantium/vm/interpreter.v +++ b/coq/ethereum/byzantium/vm/interpreter.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Interpreter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +18,18 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.trace. -Require byzantium.blocks. -Require byzantium.fork_types. -Require byzantium.state. -Require byzantium.vm. -Require byzantium.vm.gas. -Require byzantium.vm.precompiled_contracts.mapping. -Require byzantium.vm.exceptions. -Require byzantium.vm.instructions. -Require byzantium.vm.runtime. - -Definition process_message_call : M unit := +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`. @@ -47,19 +49,21 @@ Definition process_message_call : M unit := *) (* TODO statement *) (* TODO statement *) - let* tx_end := ethereum.trace.TransactionEnd (| - (* TODO expression *), - evm.["output"], - evm.["error"] - |) in - do* ethereum.trace.evm_trace (| - evm, - tx_end - |) in + 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 : M unit := +Definition process_create_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -75,26 +79,28 @@ Definition process_create_message : M unit := evm: :py:class:`~ethereum.byzantium.vm.Evm` Items containing execution specific objects. *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.destroy_storage (| - env.["state"], - message.["current_target"] - |) in - do* state.increment_nonce (| - env.["state"], - message.["current_target"] - |) in - let* evm := process_message (| - message, - env - |) in + 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 : M unit := +Definition process_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -111,23 +117,25 @@ Definition process_message : M unit := Items containing execution specific objects *) (* TODO statement *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.touch_account (| - env.["state"], - message.["current_target"] - |) in + 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 *) - let* evm := execute_code (| - message, - env - |) in + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition execute_code : M unit := +Definition execute_code (message : Message) (env : Environment) : M Evm := (* Executes bytecode present in the `message`. @@ -143,13 +151,19 @@ Definition execute_code : M unit := evm: `ethereum.vm.EVM` Items containing execution specific objects *) - let* code := message.["code"] in - let* valid_jump_destinations := runtime.get_valid_jump_destinations (| - code - |) in - let* evm := Evm (| - - |) in + 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.v b/coq/ethereum/byzantium/vm/memory.v index 94b6a44639..88b516318f 100644 --- a/coq/ethereum/byzantium/vm/memory.v +++ b/coq/ethereum/byzantium/vm/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.byte. -Definition memory_write : M unit := +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := (* Writes to memory. @@ -30,9 +31,9 @@ Definition memory_write : M unit := Data to write to memory. *) (* TODO assignment *) + M.pure tt. - -Definition memory_read_bytes : M unit := +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := (* Read bytes from memory. @@ -51,9 +52,9 @@ Definition memory_read_bytes : M unit := Data read from memory. *) (* TODO statement *) + M.pure tt. - -Definition buffer_read : M unit := +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := (* Read bytes from a buffer. Padding with zeros if necessary. @@ -72,4 +73,4 @@ Definition buffer_read : M unit := Data read from memory. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/__init__.v b/coq/ethereum/byzantium/vm/precompiled_contracts/__init__.v index 5820dc04d9..24fa6cc8c6 100644 --- a/coq/ethereum/byzantium/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,4 +14,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require byzantium.utils.hexadecimal. +Require ethereum.byzantium.utils.hexadecimal. diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.v index 632bc984ba..12fc9193b1 100644 --- a/coq/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.v +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,12 +15,12 @@ Implementation of the ALT_BN128 precompiled contracts. Require ethereum_types.numeric. Require ethereum.crypto.alt_bn128. -Require byzantium.vm. -Require byzantium.vm.gas. -Require byzantium.vm.memory. -Require byzantium.vm.exceptions. +Require ethereum.byzantium.vm. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.memory. +Require ethereum.byzantium.vm.exceptions. -Definition alt_bn128_add : M unit := +Definition alt_bn128_add (evm : Evm) : M unit := (* The ALT_BN128 addition precompiled contract. @@ -28,76 +29,96 @@ Definition alt_bn128_add : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* x1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x1_bytes - |) - |) in - let* y1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y1_bytes - |) - |) in + 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 *) - let* p := (* TODO expression *) in + do* M.assign "p" [[ + (* TODO expression *) in + ]] in (* TODO assignment *) + M.pure tt. - -Definition alt_bn128_mul : M unit := +Definition alt_bn128_mul (evm : Evm) : M unit := (* The ALT_BN128 multiplication precompiled contract. @@ -106,63 +127,77 @@ Definition alt_bn128_mul : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* n := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) (* TODO statement *) - let* p := p0.["mul_by"] (| - n - |) in + 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 : M unit := +Definition alt_bn128_pairing_check (evm : Evm) : M unit := (* The ALT_BN128 pairing check precompiled contract. @@ -171,17 +206,21 @@ Definition alt_bn128_pairing_check : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 (| + ethereum_types.numeric.Uint ~(| (* TODO expression *) |) - |) in + |) ]] in (* TODO statement *) - let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/byzantium/vm/precompiled_contracts/ecrecover.v index eddfd33ae3..243767986f 100644 --- a/coq/ethereum/byzantium/vm/precompiled_contracts/ecrecover.v +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/ecrecover.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,11 +17,11 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require byzantium.vm. -Require byzantium.vm.gas. -Require byzantium.vm.memory. +Require ethereum.byzantium.vm. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.memory. -Definition ecrecover : M unit := +Definition ecrecover (evm : Evm) : M unit := (* Decrypts the address using elliptic curve DSA recovery mechanism and writes the address to output. @@ -30,64 +31,80 @@ Definition ecrecover : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* message_hash_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* message_hash := ethereum.crypto.hash.Hash32 (| - message_hash_bytes - |) in - let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + ethereum_types.numeric.U256 ~(| + 32 |) - |) - |) in - let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 + ]] 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 *) - let* address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/byzantium/vm/precompiled_contracts/identity.v index ae43b03308..14e3685278 100644 --- a/coq/ethereum/byzantium/vm/precompiled_contracts/identity.v +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/identity.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,10 @@ Implementation of the `IDENTITY` precompiled contract. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require byzantium.vm. -Require byzantium.vm.gas. +Require ethereum.byzantium.vm. +Require ethereum.byzantium.vm.gas. -Definition identity : M unit := +Definition identity (evm : Evm) : M unit := (* Writes the message data to output. @@ -26,11 +27,15 @@ Definition identity : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/mapping.v b/coq/ethereum/byzantium/vm/precompiled_contracts/mapping.v index 73f908e4b2..286ca189f8 100644 --- a/coq/ethereum/byzantium/vm/precompiled_contracts/mapping.v +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/mapping.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Mapping of precompiled contracts their implementations. *) Require typing. -Require byzantium.fork_types. -Require byzantium.vm.precompiled_contracts.alt_bn128. -Require byzantium.vm.precompiled_contracts.ecrecover. -Require byzantium.vm.precompiled_contracts.identity. -Require byzantium.vm.precompiled_contracts.modexp. -Require byzantium.vm.precompiled_contracts.ripemd160. -Require byzantium.vm.precompiled_contracts.sha256. +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.v b/coq/ethereum/byzantium/vm/precompiled_contracts/modexp.v index 068d1d3a9f..484d94ddfc 100644 --- a/coq/ethereum/byzantium/vm/precompiled_contracts/modexp.v +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/modexp.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,100 +15,120 @@ Implementation of the `MODEXP` precompiled contract. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require byzantium.vm. -Require byzantium.vm.gas. -Require byzantium.vm.memory. +Require ethereum.byzantium.vm. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.memory. -Definition modexp : M unit := +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. *) - let* data := evm.["message"].["data"] in - let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) - |) in - let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 - let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* exp_start := (* TODO expression *) in - let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - min (| - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 |), - exp_length + ethereum_types.numeric.U256 ~(| + 32 + |) |) - |) - |) in - do* vm.gas.charge_gas (| + |) 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, - gas_cost (| - base_length, - modulus_length, - exp_length, - exp_head + 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 + |) ]] in (* TODO statement *) - let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - base_length - |) - |) in - let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - exp_length - |) - |) in - let* modulus_start := (* TODO expression *) in - let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - modulus_start, - modulus_length - |) - |) in + 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 : M unit := +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := (* Estimate the complexity of performing a modular exponentiation. @@ -126,18 +147,20 @@ Definition complexity : M unit := complexity : `Uint` Complexity of performing the operation. *) - let* max_length := max (| - ethereum_types.numeric.Uint (| - base_length - |), - ethereum_types.numeric.Uint (| - modulus_length - |) - |) in + 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 : M unit := +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := (* Calculate the number of iterations required to perform a modular exponentiation. @@ -160,9 +183,9 @@ Definition iterations : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition gas_cost : M unit := +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. @@ -188,15 +211,23 @@ Definition gas_cost : M unit := gas_cost : `Uint` Gas required for performing the operation. *) - let* multiplication_complexity := complexity (| - base_length, - modulus_length - |) in - let* iteration_count := iterations (| - exponent_length, - exponent_head - |) in - let* cost := (* TODO expression *) in - (* TODO statement *) + 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.v b/coq/ethereum/byzantium/vm/precompiled_contracts/ripemd160.v index bc5e73dd3c..fe2c66bbe6 100644 --- a/coq/ethereum/byzantium/vm/precompiled_contracts/ripemd160.v +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/ripemd160.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `RIPEMD160` precompiled contract. *) -Definition ripemd160 : M unit := +Definition ripemd160 (evm : Evm) : M unit := (* Writes the ripemd160 hash to output. @@ -22,21 +23,29 @@ Definition ripemd160 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 - let* hash_bytes := hashlib.["new"] (| - (* TODO expression *), - data - |).["digest"] (| - - |) in - let* padded_hash := left_pad_zero_bytes (| - hash_bytes, - (* TODO expression *) - |) in + |) ]] 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.v b/coq/ethereum/byzantium/vm/precompiled_contracts/sha256.v index da6972d411..3ba3ffe7aa 100644 --- a/coq/ethereum/byzantium/vm/precompiled_contracts/sha256.v +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/sha256.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `SHA256` precompiled contract. *) -Definition sha256 : M unit := +Definition sha256 (evm : Evm) : M unit := (* Writes the sha256 hash to output. @@ -22,11 +23,15 @@ Definition sha256 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/runtime.v b/coq/ethereum/byzantium/vm/runtime.v index cf779c7dd7..47bfec9776 100644 --- a/coq/ethereum/byzantium/vm/runtime.v +++ b/coq/ethereum/byzantium/vm/runtime.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Runtime Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Runtime related operations used while executing EVM code. Require typing. Require ethereum_types.numeric. -Require byzantium.vm.instructions. +Require ethereum.byzantium.vm.instructions. -Definition get_valid_jump_destinations : M unit := +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := (* Analyze the evm code to obtain the set of valid jump destinations. @@ -38,12 +39,16 @@ Definition get_valid_jump_destinations : M unit := valid_jump_destinations: `Set[Uint]` The set of valid jump destinations in the code. *) - let* valid_jump_destinations := set (| - - |) in - let* pc := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/byzantium/vm/stack.v index 78d6dbd3b7..3a9d0f579f 100644 --- a/coq/ethereum/byzantium/vm/stack.v +++ b/coq/ethereum/byzantium/vm/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Implementation of the stack operators for the EVM. Require typing. Require ethereum_types.numeric. -Require byzantium.vm.exceptions. +Require ethereum.byzantium.vm.exceptions. -Definition pop : M unit := +Definition pop (stack : (* TODO type *)) : M U256 := (* Pops the top item off of `stack`. @@ -33,9 +34,9 @@ Definition pop : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition push : M unit := +Definition push (stack : (* TODO type *)) (value : U256) : M unit := (* Pushes `value` onto `stack`. @@ -50,4 +51,4 @@ Definition push : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/cancun/__init__.v b/coq/ethereum/cancun/__init__.v index dc74124bf2..348a58a692 100644 --- a/coq/ethereum/cancun/__init__.v +++ b/coq/ethereum/cancun/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* The Cancun fork introduces transient storage, exposes beacon chain roots, introduces a new blob-carrying transaction type, adds a memory copying diff --git a/coq/ethereum/cancun/blocks.v b/coq/ethereum/cancun/blocks.v index 67586a8e3d..9bb75b168f 100644 --- a/coq/ethereum/cancun/blocks.v +++ b/coq/ethereum/cancun/blocks.v @@ -1,3 +1,4 @@ +(* 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 @@ -14,6 +15,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. -Require cancun.fork_types. -Require cancun.transactions. +Require ethereum.crypto.hash. +Require ethereum.cancun.fork_types. +Require ethereum.cancun.transactions. diff --git a/coq/ethereum/cancun/bloom.v b/coq/ethereum/cancun/bloom.v index d3e273d743..722a5958a9 100644 --- a/coq/ethereum/cancun/bloom.v +++ b/coq/ethereum/cancun/bloom.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Logs Bloom ^^^^^^^^^^^^^^^^^^^ @@ -19,10 +20,10 @@ eliminating blocks and receipts from their search. Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require cancun.blocks. -Require cancun.fork_types. +Require ethereum.cancun.blocks. +Require ethereum.cancun.fork_types. -Definition add_to_bloom : M unit := +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := (* Add a bloom entry to the bloom filter (`bloom`). @@ -37,13 +38,15 @@ Definition add_to_bloom : M unit := bloom_entry : An entry which is to be added to bloom filter. *) - let* hash := ethereum.crypto.hash.keccak256 (| - bloom_entry - |) in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition logs_bloom : M unit := +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := (* Obtain the logs bloom from a list of log entries. @@ -63,4 +66,4 @@ Definition logs_bloom : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/cancun/exceptions.v b/coq/ethereum/cancun/exceptions.v index 137ea143f6..9a313f6d0e 100644 --- a/coq/ethereum/cancun/exceptions.v +++ b/coq/ethereum/cancun/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Exceptions specific to this fork. *) diff --git a/coq/ethereum/cancun/fork.v b/coq/ethereum/cancun/fork.v index 9891312ba3..22018ff221 100644 --- a/coq/ethereum/cancun/fork.v +++ b/coq/ethereum/cancun/fork.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^ @@ -19,19 +20,21 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.exceptions. -Require cancun.blocks. -Require cancun.bloom. -Require cancun.fork_types. -Require cancun.state. -Require cancun.transactions. -Require cancun.trie. -Require cancun.utils.hexadecimal. -Require cancun.utils.message. -Require cancun.vm. -Require cancun.vm.gas. -Require cancun.vm.interpreter. - -Definition apply_fork : M unit := +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. @@ -51,9 +54,9 @@ Definition apply_fork : M unit := Upgraded block chain object for this hard fork. *) (* TODO statement *) + M.pure tt. - -Definition get_last_256_block_hashes : M unit := +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. @@ -73,22 +76,28 @@ Definition get_last_256_block_hashes : M unit := recent_block_hashes : `List[Hash32]` Hashes of the recent 256 blocks in order of increasing block number. *) - let* recent_blocks := (* TODO expression *) in - (* TODO statement *) - let* recent_block_hashes := (* TODO expression *) in - (* TODO statement *) - let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *).["header"] - |) - |) in - do* recent_block_hashes.["append"] (| - most_recent_block_hash - |) in - (* TODO statement *) - - -Definition state_transition : M unit := + 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. @@ -110,47 +119,53 @@ Definition state_transition : M unit := block : Block to apply to `chain`. *) - let* parent_header := (* TODO expression *).["header"] in - let* excess_blob_gas := vm.gas.calculate_excess_blob_gas (| - parent_header - |) in - (* TODO statement *) - do* validate_header (| - block.["header"], - parent_header - |) in - (* TODO statement *) - let* apply_body_output := apply_body (| - chain.["state"], - get_last_256_block_hashes (| - chain - |), - block.["header"].["coinbase"], - block.["header"].["number"], - block.["header"].["base_fee_per_gas"], - block.["header"].["gas_limit"], - block.["header"].["timestamp"], - block.["header"].["prev_randao"], - block.["transactions"], - chain.["chain_id"], - block.["withdrawals"], - block.["header"].["parent_beacon_block_root"], - excess_blob_gas - |) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - do* chain.["blocks"].["append"] (| + 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 + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_base_fee_per_gas : M unit := +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. @@ -170,13 +185,15 @@ Definition calculate_base_fee_per_gas : M unit := base_fee_per_gas : `Uint` Base fee per gas for the block. *) - let* parent_gas_target := (* TODO expression *) in + do* M.assign "parent_gas_target" [[ + (* TODO expression *) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition validate_header : M unit := +Definition validate_header (header : Header) (parent_header : Header) : M unit := (* Verifies a block header. @@ -195,12 +212,14 @@ Definition validate_header : M unit := Parent Header of the header to check for correctness *) (* TODO statement *) - let* expected_base_fee_per_gas := calculate_base_fee_per_gas (| - header.["gas_limit"], - parent_header.["gas_limit"], - parent_header.["gas_used"], - parent_header.["base_fee_per_gas"] - |) in + 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 *) @@ -208,15 +227,17 @@ Definition validate_header : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* block_parent_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - parent_header - |) - |) in + 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 : M unit := +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. @@ -253,23 +274,27 @@ Definition check_transaction : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* sender := recover_sender (| - chain_id, - tx - |) in - let* sender_account := state.get_account (| - state, - sender - |) in + 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 : M unit := +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. @@ -290,13 +315,15 @@ Definition make_receipt : M unit := receipt : The receipt for the transaction. *) - let* receipt := blocks.Receipt (| + do* M.assign "receipt" [[ + blocks.Receipt ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition apply_body : M unit := +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. @@ -345,43 +372,59 @@ Definition apply_body : M unit := apply_body_output : `ApplyBodyOutput` Output of applying the block body to the state. *) - let* blob_gas_used := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* gas_available := block_gas_limit in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* beacon_block_roots_contract_code := state.get_account (| - state, - BEACON_ROOTS_ADDRESS - |).["code"] in - let* system_tx_message := vm.Message (| - - |) in - let* system_tx_env := vm.["Environment"] (| - - |) in - let* system_tx_output := vm.interpreter.process_message_call (| - system_tx_message, - system_tx_env - |) in - do* state.destroy_touched_empty_accounts (| - system_tx_env.["state"], - system_tx_output.["touched_accounts"] - |) in - (* TODO statement *) - (* TODO statement *) - let* block_gas_used := (* TODO expression *) in - let* block_logs_bloom := bloom.logs_bloom (| - block_logs - |) in - (* TODO statement *) - (* TODO statement *) - - -Definition process_transaction : M unit := + 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. @@ -408,76 +451,110 @@ Definition process_transaction : M unit := logs : `Tuple[ethereum.blocks.Log, ...]` Logs generated during execution. *) - let* sender := env.["origin"] in - let* sender_account := state.get_account (| - env.["state"], - sender - |) in - (* TODO statement *) - let* effective_gas_fee := (* TODO expression *) in - let* gas := (* TODO expression *) in - do* state.increment_nonce (| - env.["state"], - sender - |) in - let* sender_balance_after_gas_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - ethereum_types.numeric.U256 (| - sender_balance_after_gas_fee + 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 - let* preaccessed_addresses := set (| - - |) in - let* preaccessed_storage_keys := set (| - - |) in - do* preaccessed_addresses.["add"] (| - env.["coinbase"] - |) in - (* TODO statement *) - let* message := utils.message.prepare_message (| - sender, - tx.["to"], - tx.["value"], - tx.["data"], - gas, - env - |) in - let* output := vm.interpreter.process_message_call (| - message, - env - |) in - let* gas_used := (* TODO expression *) in - let* gas_refund := min (| - (* TODO expression *), - ethereum_types.numeric.Uint (| - output.["refund_counter"] - |) - |) in - let* gas_refund_amount := (* TODO expression *) in - let* priority_fee_per_gas := (* TODO expression *) in - let* transaction_fee := (* TODO expression *) in - let* total_gas_used := (* TODO expression *) in - let* sender_balance_after_refund := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - sender_balance_after_refund - |) in - let* coinbase_balance_after_mining_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - do* state.destroy_touched_empty_accounts (| - env.["state"], - output.["touched_accounts"] - |) in - (* TODO statement *) - - -Definition calculate_intrinsic_cost : M unit := + |) ]] 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. @@ -500,15 +577,19 @@ Definition calculate_intrinsic_cost : M unit := verified : `ethereum.base_types.Uint` The intrinsic cost of the transaction. *) - let* data_cost := (* TODO expression *) in + do* M.assign "data_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) - let* access_list_cost := (* TODO expression *) in + do* M.assign "access_list_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition recover_sender : M unit := +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := (* Extracts the sender address from a transaction. @@ -535,9 +616,9 @@ Definition recover_sender : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_pre155 : M unit := +Definition signing_hash_pre155 (tx : LegacyTransaction) : M Hash32 := (* Compute the hash of a transaction used in a legacy (pre EIP 155) signature. @@ -552,9 +633,9 @@ Definition signing_hash_pre155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_155 : M unit := +Definition signing_hash_155 (tx : LegacyTransaction) (chain_id : U64) : M Hash32 := (* Compute the hash of a transaction used in a EIP 155 signature. @@ -571,9 +652,9 @@ Definition signing_hash_155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_2930 : M unit := +Definition signing_hash_2930 (tx : AccessListTransaction) : M Hash32 := (* Compute the hash of a transaction used in a EIP 2930 signature. @@ -588,9 +669,9 @@ Definition signing_hash_2930 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_1559 : M unit := +Definition signing_hash_1559 (tx : FeeMarketTransaction) : M Hash32 := (* Compute the hash of a transaction used in a EIP 1559 signature. @@ -605,9 +686,9 @@ Definition signing_hash_1559 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_4844 : M unit := +Definition signing_hash_4844 (tx : BlobTransaction) : M Hash32 := (* Compute the hash of a transaction used in a EIP-4844 signature. @@ -622,9 +703,9 @@ Definition signing_hash_4844 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition compute_header_hash : M unit := +Definition compute_header_hash (header : Header) : M Hash32 := (* Computes the hash of a block header. @@ -657,9 +738,9 @@ Definition compute_header_hash : M unit := Hash of the header. *) (* TODO statement *) + M.pure tt. - -Definition check_gas_limit : M unit := +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := (* Validates the gas limit for a block. @@ -687,9 +768,11 @@ Definition check_gas_limit : M unit := check : `bool` True if gas limit constraints are satisfied, False otherwise. *) - let* max_adjustment_delta := (* TODO expression *) in + 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.v b/coq/ethereum/cancun/fork_types.v index 14de99d5e5..d84cffdf45 100644 --- a/coq/ethereum/cancun/fork_types.v +++ b/coq/ethereum/cancun/fork_types.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Types ^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. +Require ethereum.__init__. +Require ethereum.crypto.hash. -Definition encode_account : M unit := +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := (* Encode `Account` dataclass. @@ -26,4 +28,4 @@ Definition encode_account : M unit := encoded without providing a storage root. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/cancun/state.v b/coq/ethereum/cancun/state.v index 30fb8778e3..f1bb1f95bc 100644 --- a/coq/ethereum/cancun/state.v +++ b/coq/ethereum/cancun/state.v @@ -1,3 +1,4 @@ +(* Generated *) (* State ^^^^^ @@ -22,11 +23,11 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require cancun.blocks. -Require cancun.fork_types. -Require cancun.trie. +Require ethereum.cancun.blocks. +Require ethereum.cancun.fork_types. +Require ethereum.cancun.trie. -Definition close_state : M unit := +Definition close_state (state : State) : M unit := (* Free resources held by the state. Used by optimized implementations to release file descriptors. @@ -35,9 +36,9 @@ Definition close_state : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition begin_transaction : M unit := +Definition begin_transaction (state : State) (transient_storage : TransientStorage) : M unit := (* Start a state transaction. @@ -51,15 +52,15 @@ Definition begin_transaction : M unit := transient_storage : TransientStorage The transient storage of the transaction. *) - do* state.["_snapshots"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - do* transient_storage.["_snapshots"].["append"] (| + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| transient_storage, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition commit_transaction : M unit := +Definition commit_transaction (state : State) (transient_storage : TransientStorage) : M unit := (* Commit a state transaction. @@ -70,16 +71,16 @@ Definition commit_transaction : M unit := transient_storage : TransientStorage The transient storage of the transaction. *) - do* state.["_snapshots"].["pop"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| - |) in + |) ]] in (* TODO statement *) - do* transient_storage.["_snapshots"].["pop"] (| - - |) in + do* [[ M.get_field ~(| M.get_field ~(| transient_storage, "_snapshots" |), "pop" |) ~(| + |) ]] in + M.pure tt. -Definition rollback_transaction : M unit := +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. @@ -94,9 +95,9 @@ Definition rollback_transaction : M unit := (* TODO assignment *) (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition get_account : M unit := +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. @@ -116,14 +117,16 @@ Definition get_account : M unit := account : `Account` Account at address. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition get_account_optional : M unit := +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. @@ -140,14 +143,16 @@ Definition get_account_optional : M unit := account : `Account` Account at address. *) - let* account := trie.trie_get (| - state.["_main_trie"], - address - |) in + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition set_account : M unit := +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()`). @@ -161,14 +166,14 @@ Definition set_account : M unit := account : `Account` Account to set at address. *) - do* trie.trie_set (| - state.["_main_trie"], + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), address, account - |) in + |) ]] in + M.pure tt. - -Definition destroy_account : M unit := +Definition destroy_account (state : State) (address : Address) : M unit := (* Completely remove the account at `address` and all of its storage. @@ -183,18 +188,18 @@ Definition destroy_account : M unit := address : `Address` Address of account to destroy. *) - do* destroy_storage (| + do* [[ M.get_local ~(| "destroy_storage" |) ~(| state, address - |) in - do* set_account (| + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - (* TODO expression *) - |) in - + tt + |) ]] in + M.pure tt. -Definition destroy_storage : M unit := +Definition destroy_storage (state : State) (address : Address) : M unit := (* Completely remove the storage at `address`. @@ -206,9 +211,9 @@ Definition destroy_storage : M unit := Address of account whose storage is to be deleted. *) (* TODO statement *) + M.pure tt. - -Definition mark_account_created : M unit := +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 @@ -225,12 +230,12 @@ Definition mark_account_created : M unit := address : `Address` Address of the account that has been created. *) - do* state.["created_accounts"].["add"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| address - |) in - + |) ]] in + M.pure tt. -Definition get_storage : M unit := +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. @@ -249,19 +254,23 @@ Definition get_storage : M unit := value : `U256` Value at the key. *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition set_storage : M unit := +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. @@ -278,19 +287,21 @@ Definition set_storage : M unit := Value to set at the key. *) (* TODO statement *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - do* trie.trie_set (| - trie, + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), key, value - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition storage_root : M unit := +Definition storage_root (state : State) (address : Address) : M Root := (* Calculate the storage root of an account. @@ -308,9 +319,9 @@ Definition storage_root : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition state_root : M unit := +Definition state_root (state : State) : M Root := (* Calculate the state root. @@ -327,9 +338,9 @@ Definition state_root : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition account_exists : M unit := +Definition account_exists (state : State) (address : Address) : M bool := (* Checks if an account exists in the state trie @@ -346,9 +357,9 @@ Definition account_exists : M unit := True if account exists in the state trie, False otherwise *) (* TODO statement *) + M.pure tt. - -Definition account_has_code_or_nonce : M unit := +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := (* Checks if an account has non zero nonce or non empty code @@ -365,14 +376,16 @@ Definition account_has_code_or_nonce : M unit := True if if an account has non zero nonce or non empty code, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_empty : M unit := +Definition is_account_empty (state : State) (address : Address) : M bool := (* Checks if an account has zero nonce, empty code and zero balance. @@ -389,14 +402,16 @@ Definition is_account_empty : M unit := True if if an account has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition account_exists_and_is_empty : M unit := +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. @@ -414,14 +429,16 @@ Definition account_exists_and_is_empty : M unit := True if an account exists and has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_alive : M unit := +Definition is_account_alive (state : State) (address : Address) : M bool := (* Check whether is an account is both in the state and non empty. @@ -437,61 +454,63 @@ Definition is_account_alive : M unit := is_alive : `bool` True if the account is alive. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition modify_state : M unit := +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := (* Modify an `Account` in the `State`. *) - do* set_account (| + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - ethereum_types.frozen.modify (| - get_account (| + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| state, address |), f |) - |) in + |) ]] in + M.pure tt. - -Definition move_ether : M unit := +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := (* Move funds between accounts. *) (* TODO statement *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, sender_address, - reduce_sender_balance - |) in - do* modify_state (| + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| state, recipient_address, - increase_recipient_balance - |) in - + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. -Definition process_withdrawal : M unit := +Definition process_withdrawal (state : State) (wd : Withdrawal) : M unit := (* Increase the balance of the withdrawing account. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, - wd.["address"], - increase_recipient_balance - |) in - + M.get_field ~(| wd, "address" |), + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. -Definition set_account_balance : M unit := +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := (* Sets the balance of an account. @@ -507,14 +526,14 @@ Definition set_account_balance : M unit := The amount that needs to set in balance. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - set_balance - |) in + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. - -Definition touch_account : M unit := +Definition touch_account (state : State) (address : Address) : M unit := (* Initializes an account to state. @@ -527,9 +546,9 @@ Definition touch_account : M unit := The address of the account that need to initialised. *) (* TODO statement *) + M.pure tt. - -Definition increment_nonce : M unit := +Definition increment_nonce (state : State) (address : Address) : M unit := (* Increments the nonce of an account. @@ -542,14 +561,14 @@ Definition increment_nonce : M unit := Address of the account whose nonce needs to be incremented. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_nonce - |) in - + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. -Definition set_code : M unit := +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := (* Sets Account code. @@ -565,14 +584,14 @@ Definition set_code : M unit := The bytecode that needs to be set. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - write_code - |) in + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. - -Definition get_storage_original : M unit := +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 @@ -589,15 +608,17 @@ Definition get_storage_original : M unit := *) (* TODO statement *) (* TODO assignment *) - let* original_account_trie := original_trie.["get"] (| - address - |) in + 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 : M unit := +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. @@ -614,19 +635,23 @@ Definition get_transient_storage : M unit := value : `U256` Value at the key. *) - let* trie := transient_storage.["_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| transient_storage, "_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + 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 : M unit := +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. @@ -641,19 +666,21 @@ Definition set_transient_storage : M unit := value : `U256` Value to set at the key. *) - let* trie := transient_storage.["_tries"].["get"] (| - address - |) in - (* TODO statement *) - do* trie.trie_set (| - trie, + 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 + |) ]] in (* TODO statement *) + M.pure tt. - -Definition destroy_touched_empty_accounts : M unit := +Definition destroy_touched_empty_accounts (state : State) (touched_accounts : (* TODO type *)) : M unit := (* Destroy all touched accounts that are empty. Parameters @@ -664,4 +691,4 @@ Definition destroy_touched_empty_accounts : M unit := All the accounts that have been touched in the current transaction. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/cancun/transactions.v b/coq/ethereum/cancun/transactions.v index ba22e3d536..530970c094 100644 --- a/coq/ethereum/cancun/transactions.v +++ b/coq/ethereum/cancun/transactions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, @@ -9,19 +10,20 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require cancun.exceptions. -Require cancun.fork_types. +Require ethereum.__init__. +Require ethereum.cancun.exceptions. +Require ethereum.cancun.fork_types. -Definition encode_transaction : M unit := +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 : M unit := +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.v b/coq/ethereum/cancun/trie.v index 5f0ab29642..3b45315972 100644 --- a/coq/ethereum/cancun/trie.v +++ b/coq/ethereum/cancun/trie.v @@ -1,3 +1,4 @@ +(* Generated *) (* State Trie ^^^^^^^^^^ @@ -14,7 +15,7 @@ The state trie is the structure responsible for storing *) -Definition encode_internal_node : M unit := +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 @@ -35,22 +36,24 @@ Definition encode_internal_node : M unit := *) (* TODO statement *) (* TODO statement *) - let* encoded := rlp.["encode"] (| - unencoded - |) in + 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 : M unit := +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 : M unit := +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. @@ -66,9 +69,9 @@ Definition copy_trie : M unit := A copy of the trie. *) (* TODO statement *) + M.pure tt. - -Definition trie_set : M unit := +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := (* Stores an item in a Merkle Trie. @@ -85,9 +88,9 @@ Definition trie_set : M unit := Node to insert at `key`. *) (* TODO statement *) + M.pure tt. - -Definition trie_get : M unit := +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := (* Gets an item from the Merkle Trie. @@ -106,17 +109,17 @@ Definition trie_get : M unit := Node at `key` in the trie. *) (* TODO statement *) + M.pure tt. - -Definition common_prefix_length : M unit := +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 : M unit := +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := (* Compresses nibble-list into a standard byte array with a flag. @@ -150,14 +153,16 @@ Definition nibble_list_to_compact : M unit := compressed : `bytearray` Compact byte array. *) - let* compact := bytearray (| + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition bytes_to_nibble_list : M unit := +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := (* Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). @@ -171,14 +176,16 @@ Definition bytes_to_nibble_list : M unit := nibble_list : `Bytes` The `Bytes` in nibble-list format. *) - let* nibble_list := bytearray (| - (* TODO expression *) - |) in + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _prepare_trie : M unit := +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. @@ -199,9 +206,9 @@ Definition _prepare_trie : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition root : M unit := +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := (* Computes the root of a modified merkle patricia trie (MPT). @@ -219,22 +226,26 @@ Definition root : M unit := root : `.fork_types.Root` MPT root of the underlying key-value pairs. *) - let* obj := _prepare_trie (| - trie, - get_storage_root - |) in - let* root_node := encode_internal_node (| - patricialize (| - obj, - Uint (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) + M.pure tt. - -Definition patricialize : M unit := +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := (* Structural composition function. @@ -254,21 +265,29 @@ Definition patricialize : M unit := Root node of `obj`. *) (* TODO statement *) - let* arbitrary_key := next (| - iter (| - obj - |) - |) in + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in (* TODO statement *) - let* substring := (* TODO expression *) in - let* prefix_length := len (| - substring - |) in + 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 *) - let* value := (* TODO expression *) in + do* M.assign "value" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/cancun/utils/__init__.v b/coq/ethereum/cancun/utils/__init__.v index beff4482b1..7f30fe939b 100644 --- a/coq/ethereum/cancun/utils/__init__.v +++ b/coq/ethereum/cancun/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions unique to this particular fork. *) diff --git a/coq/ethereum/cancun/utils/address.v b/coq/ethereum/cancun/utils/address.v index 9bbf4aa8d6..f4f3877242 100644 --- a/coq/ethereum/cancun/utils/address.v +++ b/coq/ethereum/cancun/utils/address.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,9 +19,10 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require cancun.fork_types. +Require ethereum.__init__. +Require ethereum.cancun.fork_types. -Definition to_address : M unit := +Definition to_address (data : (* TODO type *)) : M Address := (* Convert a Uint or U256 value to a valid address (20 bytes). @@ -35,9 +37,9 @@ Definition to_address : M unit := The obtained address. *) (* TODO statement *) + M.pure tt. - -Definition compute_contract_address : M unit := +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := (* Computes address of the new account that needs to be created. @@ -54,20 +56,26 @@ Definition compute_contract_address : M unit := address: `Address` The computed address of the new account. *) - let* computed_address := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *) - |) - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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 : M unit := +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. @@ -86,14 +94,22 @@ Definition compute_create2_contract_address : M unit := address: `ethereum.cancun.fork_types.Address` The computed address of the new account. *) - let* preimage := (* TODO expression *) in - let* computed_address := ethereum.crypto.hash.keccak256 (| - preimage - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/cancun/utils/hexadecimal.v index 3e508da3cd..ac8639bbe3 100644 --- a/coq/ethereum/cancun/utils/hexadecimal.v +++ b/coq/ethereum/cancun/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Cancun types. *) Require ethereum.utils.hexadecimal. -Require cancun.fork_types. +Require ethereum.cancun.fork_types. -Definition hex_to_root : M unit := +Definition hex_to_root (hex_string : str) : M Root := (* Convert hex string to trie root. @@ -31,9 +32,9 @@ Definition hex_to_root : M unit := Trie root obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bloom : M unit := +Definition hex_to_bloom (hex_string : str) : M Bloom := (* Convert hex string to bloom. @@ -48,9 +49,9 @@ Definition hex_to_bloom : M unit := Bloom obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_address : M unit := +Definition hex_to_address (hex_string : str) : M Address := (* Convert hex string to Address (20 bytes). @@ -65,4 +66,4 @@ Definition hex_to_address : M unit := The address obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/cancun/utils/message.v b/coq/ethereum/cancun/utils/message.v index 838fd3ca6b..f674f71474 100644 --- a/coq/ethereum/cancun/utils/message.v +++ b/coq/ethereum/cancun/utils/message.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For The Message Data-structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,13 +17,13 @@ specification. Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require cancun.fork_types. -Require cancun.state. -Require cancun.vm. -Require cancun.vm.precompiled_contracts.mapping. -Require cancun.utils.address. +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 : M unit := +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. @@ -61,22 +62,24 @@ Definition prepare_message : M unit := Items containing contract creation or message call specific data. *) (* TODO statement *) - let* accessed_addresses := set (| + do* M.assign "accessed_addresses" [[ + M.get_local ~(| "set" |) ~(| - |) in - do* accessed_addresses.["add"] (| - current_target - |) in - do* accessed_addresses.["add"] (| + |) 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* accessed_addresses.["update"] (| - vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS.["keys"] (| + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS, "keys" |) ~(| |) - |) in - do* accessed_addresses.["update"] (| + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| preaccessed_addresses - |) in + |) ]] in (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/cancun/vm/__init__.v b/coq/ethereum/cancun/vm/__init__.v index d124609337..76bc5c2d6a 100644 --- a/coq/ethereum/cancun/vm/__init__.v +++ b/coq/ethereum/cancun/vm/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,12 +19,12 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require cancun.blocks. -Require cancun.fork_types. -Require cancun.state. -Require cancun.vm.precompiled_contracts. +Require ethereum.cancun.blocks. +Require ethereum.cancun.fork_types. +Require ethereum.cancun.state. +Require ethereum.cancun.vm.precompiled_contracts. -Definition incorporate_child_on_success : M unit := +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of a successful `child_evm` into the parent `evm`. @@ -34,25 +35,31 @@ Definition incorporate_child_on_success : M unit := 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 *) - (* TODO statement *) - (* TODO statement *) - do* evm.["accounts_to_delete"].["update"] (| - child_evm.["accounts_to_delete"] - |) in - do* evm.["touched_accounts"].["update"] (| - child_evm.["touched_accounts"] - |) in - (* TODO statement *) - do* evm.["accessed_addresses"].["update"] (| - child_evm.["accessed_addresses"] - |) in - do* evm.["accessed_storage_keys"].["update"] (| - child_evm.["accessed_storage_keys"] - |) in + 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 : M unit := +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. @@ -65,5 +72,7 @@ Definition incorporate_child_on_error : M unit := *) (* TODO statement *) (* 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.v b/coq/ethereum/cancun/vm/exceptions.v index 1784494410..47e26555d5 100644 --- a/coq/ethereum/cancun/vm/exceptions.v +++ b/coq/ethereum/cancun/vm/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Exceptions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/cancun/vm/gas.v b/coq/ethereum/cancun/vm/gas.v index a9c53398b9..6b09f8bc61 100644 --- a/coq/ethereum/cancun/vm/gas.v +++ b/coq/ethereum/cancun/vm/gas.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Gas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,11 +18,12 @@ Require typing. Require ethereum_types.numeric. Require ethereum.trace. Require ethereum.utils.numeric. -Require cancun.blocks. -Require cancun.transactions. -Require cancun.vm.exceptions. +Require ethereum.cancun.blocks. +Require ethereum.cancun.transactions. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.exceptions. -Definition charge_gas : M unit := +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := (* Subtracts `amount` from `evm.gas_left`. @@ -33,18 +35,18 @@ Definition charge_gas : M unit := The amount of gas the current operation requires. *) - do* ethereum.trace.evm_trace (| + do* [[ ethereum.trace.evm_trace ~(| evm, - ethereum.trace.GasAndRefund (| - int (| + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| amount |) |) - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_memory_gas_cost : M unit := +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, @@ -60,14 +62,22 @@ Definition calculate_memory_gas_cost : M unit := total_gas_cost : `ethereum.base_types.Uint` The gas cost for storing data in memory. *) - let* size_in_words := (* TODO expression *) in - let* linear_cost := (* TODO expression *) in - let* quadratic_cost := (* TODO expression *) in - let* total_gas_cost := (* TODO expression *) in + 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 : M unit := +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := (* Calculates the gas amount to extend memory @@ -83,22 +93,28 @@ Definition calculate_gas_extend_memory : M unit := ------- extend_memory: `ExtendMemory` *) - let* size_to_extend := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* to_be_paid := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* current_size := ethereum_types.numeric.Uint (| - len (| - memory - |) - |) in + 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 : M unit := +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. @@ -124,18 +140,22 @@ Definition calculate_message_call_gas : M unit := ------- message_call_gas: `MessageCallGas` *) - let* call_stipend := (* TODO expression *) in + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* gas := min (| - gas, - max_message_call_gas (| - (* TODO expression *) - |) - |) in + 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 : M unit := +Definition max_message_call_gas (gas : Uint) : M Uint := (* Calculates the maximum gas that is allowed for making a message call @@ -150,9 +170,9 @@ Definition max_message_call_gas : M unit := The maximum gas allowed for making the message-call. *) (* TODO statement *) + M.pure tt. - -Definition init_code_cost : M unit := +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. @@ -169,9 +189,9 @@ Definition init_code_cost : M unit := The gas to be charged for the init code. *) (* TODO statement *) + M.pure tt. - -Definition calculate_excess_blob_gas : M unit := +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. @@ -186,18 +206,24 @@ Definition calculate_excess_blob_gas : M unit := excess_blob_gas: `ethereum.base_types.U64` The excess blob gas for the current block. *) - let* excess_blob_gas := ethereum_types.numeric.U64 (| - (* TODO expression *) - |) in - let* blob_gas_used := ethereum_types.numeric.U64 (| - (* TODO expression *) - |) in + 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 *) - let* parent_blob_gas := (* TODO expression *) in + do* M.assign "parent_blob_gas" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_total_blob_gas : M unit := +Definition calculate_total_blob_gas (tx : Transaction) : M Uint := (* Calculate the total blob gas for a transaction. @@ -212,9 +238,9 @@ Definition calculate_total_blob_gas : M unit := The total blob gas for the transaction. *) (* TODO statement *) + M.pure tt. - -Definition calculate_blob_gas_price : M unit := +Definition calculate_blob_gas_price (excess_blob_gas : U64) : M Uint := (* Calculate the blob gasprice for a block. @@ -229,9 +255,9 @@ Definition calculate_blob_gas_price : M unit := The blob gasprice. *) (* TODO statement *) + M.pure tt. - -Definition calculate_data_fee : M unit := +Definition calculate_data_fee (excess_blob_gas : U64) (tx : Transaction) : M Uint := (* Calculate the blob data fee for a transaction. @@ -248,4 +274,4 @@ Definition calculate_data_fee : M unit := The blob data fee. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/cancun/vm/instructions/__init__.v b/coq/ethereum/cancun/vm/instructions/__init__.v index b36b1ebfef..cbd7e7e63a 100644 --- a/coq/ethereum/cancun/vm/instructions/__init__.v +++ b/coq/ethereum/cancun/vm/instructions/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* EVM Instruction Encoding (Opcodes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/cancun/vm/instructions/arithmetic.v b/coq/ethereum/cancun/vm/instructions/arithmetic.v index 1ae5a794a3..221e17dee5 100644 --- a/coq/ethereum/cancun/vm/instructions/arithmetic.v +++ b/coq/ethereum/cancun/vm/instructions/arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,11 @@ Implementations of the EVM Arithmetic instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require cancun.vm.gas. -Require cancun.vm.stack. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.stack. -Definition add : M unit := +Definition add (evm : Evm) : M unit := (* Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -28,27 +30,37 @@ Definition add : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_add"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sub (evm : Evm) : M unit := (* Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -59,27 +71,37 @@ Definition sub : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_sub"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mul (evm : Evm) : M unit := (* Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -90,27 +112,37 @@ Definition mul : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_mul"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition div (evm : Evm) : M unit := (* Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -121,25 +153,33 @@ Definition div : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |) in - let* divisor := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - quotient - |) 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 : M unit := +Definition sdiv (evm : Evm) : M unit := (* Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -150,31 +190,39 @@ Definition sdiv : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* divisor := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - quotient + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mod : M unit := +Definition mod (evm : Evm) : M unit := (* Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -185,25 +233,33 @@ Definition mod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - remainder - |) in + |) ]] 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 : M unit := +Definition smod (evm : Evm) : M unit := (* Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -214,31 +270,39 @@ Definition smod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* y := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - remainder + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition addmod : M unit := +Definition addmod (evm : Evm) : M unit := (* Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -249,34 +313,44 @@ Definition addmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +Definition mulmod (evm : Evm) : M unit := (* Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -287,34 +361,44 @@ Definition mulmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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 : M unit := +Definition exp (evm : Evm) : M unit := (* Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -325,39 +409,53 @@ Definition exp : M unit := The current EVM frame. *) - let* base := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent_bits := exponent.["bit_length"] (| - - |) in - let* exponent_bytes := (* TODO expression *) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - pow (| - base, - exponent, - (* 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 - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition signextend : M unit := +Definition signextend (evm : Evm) : M unit := (* Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -368,20 +466,28 @@ Definition signextend : M unit := The current EVM frame. *) - let* byte_num := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/cancun/vm/instructions/bitwise.v index 978e05422b..4a3d09cf84 100644 --- a/coq/ethereum/cancun/vm/instructions/bitwise.v +++ b/coq/ethereum/cancun/vm/instructions/bitwise.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Bitwise Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM bitwise instructions. *) Require ethereum_types.numeric. -Require cancun.vm.gas. -Require cancun.vm.stack. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.stack. -Definition bitwise_and : M unit := +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. @@ -27,24 +29,32 @@ Definition bitwise_and : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_or : M unit := +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. @@ -55,24 +65,32 @@ Definition bitwise_or : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_xor : M unit := +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. @@ -83,24 +101,32 @@ Definition bitwise_xor : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_not : M unit := +Definition bitwise_not (evm : Evm) : M unit := (* Bitwise NOT operation of the top element of the stack. Pushes the result back on the stack. @@ -111,21 +137,27 @@ Definition bitwise_not : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition get_byte : M unit := +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 @@ -137,25 +169,33 @@ Definition get_byte : M unit := The current EVM frame. *) - let* byte_index := stack.pop (| - evm.["stack"] - |) in - let* word := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -164,29 +204,37 @@ Definition bitwise_shl : M unit := evm : The current EVM frame. *) - let* shift := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -195,25 +243,33 @@ Definition bitwise_shr : M unit := evm : The current EVM frame. *) - let* shift := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -222,24 +278,32 @@ Definition bitwise_sar : M unit := evm : The current EVM frame. *) - let* shift := int (| - stack.pop (| - evm.["stack"] - |) - |) in - let* signed_value := stack.pop (| - evm.["stack"] - |).["to_signed"] (| + 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 - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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.v b/coq/ethereum/cancun/vm/instructions/block.v index 7a939e8b86..20caf34a0d 100644 --- a/coq/ethereum/cancun/vm/instructions/block.v +++ b/coq/ethereum/cancun/vm/instructions/block.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Block Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM block instructions. *) Require ethereum_types.numeric. -Require cancun.vm.gas. -Require cancun.vm.stack. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.stack. -Definition block_hash : M unit := +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. @@ -33,27 +35,35 @@ Definition block_hash : M unit := :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError` If `evm.gas_left` is less than `20`. *) - let* block_number := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* max_block_number := (* TODO expression *) in + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition coinbase : M unit := +Definition coinbase (evm : Evm) : M unit := (* Push the current block's beneficiary address (address of the block miner) onto the stack. @@ -74,20 +84,24 @@ Definition coinbase : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["coinbase"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition timestamp : M unit := +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. @@ -108,18 +122,22 @@ Definition timestamp : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["env"].["time"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition number (evm : Evm) : M unit := (* Push the current block's number onto the stack. @@ -139,20 +157,24 @@ Definition number : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["number"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition prev_randao : M unit := +Definition prev_randao (evm : Evm) : M unit := (* Push the `prev_randao` value onto the stack. @@ -172,20 +194,24 @@ Definition prev_randao : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["prev_randao"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_limit : M unit := +Definition gas_limit (evm : Evm) : M unit := (* Push the current block's gas limit onto the stack. @@ -205,20 +231,24 @@ Definition gas_limit : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_limit"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition chain_id : M unit := +Definition chain_id (evm : Evm) : M unit := (* Push the chain id onto the stack. @@ -235,15 +265,19 @@ Definition chain_id : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["chain_id"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/cancun/vm/instructions/comparison.v index 93d8d576f0..e04e5c9ca2 100644 --- a/coq/ethereum/cancun/vm/instructions/comparison.v +++ b/coq/ethereum/cancun/vm/instructions/comparison.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Comparison Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM Comparison instructions. *) Require ethereum_types.numeric. -Require cancun.vm.gas. -Require cancun.vm.stack. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.stack. -Definition less_than : M unit := +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. @@ -27,27 +29,37 @@ Definition less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_less_than : M unit := + |) ]] 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. @@ -57,31 +69,41 @@ Definition signed_less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition greater_than : M unit := + |) ]] 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. @@ -92,27 +114,37 @@ Definition greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_greater_than : M unit := + |) ]] 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. @@ -122,31 +154,41 @@ Definition signed_greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition equal : M unit := + |) ]] 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. @@ -157,27 +199,37 @@ Definition equal : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition is_zero : M unit := + |) ]] 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. @@ -188,19 +240,27 @@ Definition is_zero : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/cancun/vm/instructions/control_flow.v index f15822fe1f..958c0bd396 100644 --- a/coq/ethereum/cancun/vm/instructions/control_flow.v +++ b/coq/ethereum/cancun/vm/instructions/control_flow.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Control Flow Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM control flow instructions. *) Require ethereum_types.numeric. -Require cancun.vm.gas. -Require cancun.vm.exceptions. -Require cancun.vm.stack. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.exceptions. +Require ethereum.cancun.vm.stack. -Definition stop : M unit := +Definition stop (evm : Evm) : M unit := (* Stop further execution of EVM code. @@ -29,10 +31,14 @@ Definition stop : M unit := (* TODO statement *) (* TODO statement *) (* TODO assignment *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jump : M unit := +Definition jump (evm : Evm) : M unit := (* Alter the program counter to the location specified by the top of the stack. @@ -43,20 +49,22 @@ Definition jump : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition jumpi : M unit := +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 @@ -68,23 +76,27 @@ Definition jumpi : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* conditional_value := stack.pop (| - evm.["stack"] - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition pc : M unit := +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. @@ -96,20 +108,24 @@ Definition pc : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["pc"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_left : M unit := +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. @@ -121,20 +137,24 @@ Definition gas_left : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["gas_left"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jumpdest : M unit := +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 @@ -147,10 +167,14 @@ Definition jumpdest : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_JUMPDEST - |) in - (* TODO statement *) + |) ]] 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.v b/coq/ethereum/cancun/vm/instructions/environment.v index 69e3767e9f..cfdf2a756d 100644 --- a/coq/ethereum/cancun/vm/instructions/environment.v +++ b/coq/ethereum/cancun/vm/instructions/environment.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,15 +17,16 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require cancun.fork_types. -Require cancun.state. -Require cancun.utils.address. -Require cancun.vm.memory. -Require cancun.vm.exceptions. -Require cancun.vm.gas. -Require cancun.vm.stack. - -Definition address : M unit := +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. @@ -35,20 +37,24 @@ Definition address : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["current_target"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition balance : M unit := +Definition balance (evm : Evm) : M unit := (* Pushes the balance of the given account onto the stack. @@ -58,24 +64,32 @@ Definition balance : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] + 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 - (* TODO statement *) - let* balance := state.get_account (| - evm.["env"].["state"], - address - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition origin : M unit := +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. @@ -87,20 +101,24 @@ Definition origin : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["origin"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition caller : M unit := +Definition caller (evm : Evm) : M unit := (* Pushes the address of the caller onto the stack. @@ -111,20 +129,24 @@ Definition caller : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["caller"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition callvalue : M unit := +Definition callvalue (evm : Evm) : M unit := (* Push the value (in wei) sent with the call onto the stack. @@ -135,18 +157,22 @@ Definition callvalue : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["message"].["value"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition calldataload (evm : Evm) : M unit := (* Push a word (32 bytes) of the input data belonging to the current environment onto the stack. @@ -157,30 +183,38 @@ Definition calldataload : M unit := The current EVM frame. *) - let* start_index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - start_index, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] 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* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - value + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 |) - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition calldatasize : M unit := +Definition calldatasize (evm : Evm) : M unit := (* Push the size of input data in current environment onto the stack. @@ -191,22 +225,26 @@ Definition calldatasize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["message"].["data"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition calldatacopy : M unit := +Definition calldatacopy (evm : Evm) : M unit := (* Copy a portion of the input data in current environment to memory. @@ -219,40 +257,60 @@ Definition calldatacopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* data_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - data_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition codesize (evm : Evm) : M unit := (* Push the size of code running in current environment onto the stack. @@ -263,22 +321,26 @@ Definition codesize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["code"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition codecopy : M unit := +Definition codecopy (evm : Evm) : M unit := (* Copy a portion of the code in current environment to memory. @@ -291,40 +353,60 @@ Definition codecopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["code"], - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition gasprice (evm : Evm) : M unit := (* Push the gas price used in current environment onto the stack. @@ -335,20 +417,24 @@ Definition gasprice : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_price"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition extcodesize : M unit := +Definition extcodesize (evm : Evm) : M unit := (* Push the code size of a given account onto the stack. @@ -358,28 +444,36 @@ Definition extcodesize : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - (* TODO statement *) - let* codesize := ethereum_types.numeric.U256 (| - len (| - state.get_account (| - evm.["env"].["state"], - address - |).["code"] + 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 - do* stack.push (| - evm.["stack"], - codesize - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition extcodecopy : M unit := +Definition extcodecopy (evm : Evm) : M unit := (* Copy a portion of an account's code to memory. @@ -389,46 +483,70 @@ Definition extcodecopy : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - (* TODO statement *) - let* code := state.get_account (| - evm.["env"].["state"], - address - |).["code"] in - let* value := vm.memory.buffer_read (| - code, - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in + 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 : M unit := +Definition returndatasize (evm : Evm) : M unit := (* Pushes the size of the return data buffer onto the stack. @@ -438,22 +556,26 @@ Definition returndatasize : M unit := The current EVM frame. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["return_data"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition returndatacopy : M unit := +Definition returndatacopy (evm : Evm) : M unit := (* Copies data from the return data buffer code to memory @@ -462,37 +584,57 @@ Definition returndatacopy : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* return_data_start_position := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) + |) ]] in (* TODO statement *) - let* value := (* TODO expression *) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) 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 : M unit := +Definition extcodehash (evm : Evm) : M unit := (* Returns the keccak256 hash of a contract’s bytecode Parameters @@ -500,25 +642,33 @@ Definition extcodehash : M unit := evm : The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] + 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 - (* TODO statement *) - let* account := state.get_account (| - evm.["env"].["state"], - address - |) in - (* TODO statement *) - do* stack.push (| - evm.["stack"], - codehash - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition self_balance : M unit := +Definition self_balance (evm : Evm) : M unit := (* Pushes the balance of the current address to the stack. @@ -529,22 +679,28 @@ Definition self_balance : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_FAST_STEP - |) in - let* balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition base_fee (evm : Evm) : M unit := (* Pushes the base fee of the current block on to the stack. @@ -555,20 +711,24 @@ Definition base_fee : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["base_fee_per_gas"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition blob_hash : M unit := +Definition blob_hash (evm : Evm) : M unit := (* Pushes the versioned hash at a particular index on to the stack. @@ -578,24 +738,30 @@ Definition blob_hash : M unit := The current EVM frame. *) - let* index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BLOBHASH_OPCODE - |) in + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - blob_hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "blob_hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition blob_base_fee : M unit := +Definition blob_base_fee (evm : Evm) : M unit := (* Pushes the blob base fee on to the stack. @@ -606,18 +772,24 @@ Definition blob_base_fee : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - let* blob_base_fee := gas.calculate_blob_gas_price (| - evm.["env"].["excess_blob_gas"] - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - blob_base_fee + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/cancun/vm/instructions/keccak.v index d306b4810f..c0f33ddc8d 100644 --- a/coq/ethereum/cancun/vm/instructions/keccak.v +++ b/coq/ethereum/cancun/vm/instructions/keccak.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Keccak Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM keccak instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require cancun.vm.gas. -Require cancun.vm.memory. -Require cancun.vm.stack. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.memory. +Require ethereum.cancun.vm.stack. -Definition keccak : M unit := +Definition keccak (evm : Evm) : M unit := (* Pushes to the stack the Keccak-256 hash of a region of memory. @@ -32,36 +34,56 @@ Definition keccak : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* word_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in - let* hash := ethereum.crypto.hash.keccak256 (| - data - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/cancun/vm/instructions/log.v index c7a64b184c..d1439aa2d8 100644 --- a/coq/ethereum/cancun/vm/instructions/log.v +++ b/coq/ethereum/cancun/vm/instructions/log.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Logging Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,13 +15,14 @@ Implementations of the EVM logging instructions. Require functools. Require ethereum_types.numeric. -Require cancun.blocks. -Require cancun.vm.exceptions. -Require cancun.vm.gas. -Require cancun.vm.memory. -Require cancun.vm.stack. +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 : M unit := +Definition log_n (evm : Evm) (num_topics : U256) : M unit := (* Appends a log entry, having `num_topics` topics, to the evm logs. @@ -35,27 +37,43 @@ Definition log_n : M unit := The number of topics to be included in the log entry. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* topics := (* TODO expression *) in + 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 *) - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in (* TODO statement *) - let* log_entry := blocks.Log (| + do* M.assign "log_entry" [[ + blocks.Log ~(| - |) in + |) in + ]] in (* TODO assignment *) - (* 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/memory.v b/coq/ethereum/cancun/vm/instructions/memory.v index 5c969b84b8..e423105fad 100644 --- a/coq/ethereum/cancun/vm/instructions/memory.v +++ b/coq/ethereum/cancun/vm/instructions/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM Memory instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require cancun.vm.gas. -Require cancun.vm.memory. -Require cancun.vm.stack. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.memory. +Require ethereum.cancun.vm.stack. -Definition mstore : M unit := +Definition mstore (evm : Evm) : M unit := (* Stores a word to memory. This also expands the memory, if the memory is @@ -31,32 +33,44 @@ Definition mstore : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* memory.memory_write (| - evm.["memory"], - start_position, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mstore8 (evm : Evm) : M unit := (* Stores a byte to memory. This also expands the memory, if the memory is @@ -68,33 +82,47 @@ Definition mstore8 : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ (* TODO expression *) - |) in - do* memory.memory_write (| - evm.["memory"], - start_position, - normalized_bytes_value - |) in - (* TODO statement *) - + ]] 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 : M unit := +Definition mload (evm : Evm) : M unit := (* Load word from memory. @@ -104,35 +132,47 @@ Definition mload : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.memory_read_bytes (| - evm.["memory"], - start_position, - ethereum_types.numeric.U256 (| - (* 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 - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition msize : M unit := +Definition msize (evm : Evm) : M unit := (* Push the size of active memory in bytes onto the stack. @@ -143,22 +183,26 @@ Definition msize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["memory"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mcopy : M unit := +Definition mcopy (evm : Evm) : M unit := (* Copy the bytes in memory from one location to another. @@ -168,35 +212,55 @@ Definition mcopy : M unit := The current EVM frame. *) - let* destination := stack.pop (| - evm.["stack"] - |) in - let* source := stack.pop (| - evm.["stack"] - |) in - let* length := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := memory.memory_read_bytes (| - evm.["memory"], - source, - length - |) in - do* memory.memory_write (| - evm.["memory"], - destination, - value - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/cancun/vm/instructions/stack.v index 7ff41be559..892e22ae4a 100644 --- a/coq/ethereum/cancun/vm/instructions/stack.v +++ b/coq/ethereum/cancun/vm/instructions/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM stack related instructions. Require functools. Require ethereum_types.numeric. -Require cancun.vm.exceptions. -Require cancun.vm.gas. -Require cancun.vm.memory. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.exceptions. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.memory. -Definition pop : M unit := +Definition pop (evm : Evm) : M unit := (* Remove item from stack. @@ -28,18 +30,22 @@ Definition pop : M unit := The current EVM frame. *) - do* stack.["pop"] (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in + |) ]] in (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition push_n : M unit := +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. @@ -55,25 +61,29 @@ Definition push_n : M unit := *) (* TODO statement *) (* TODO statement *) - let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - evm.["code"], - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - num_bytes + 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 - do* stack.["push"] (| - evm.["stack"], - data_to_push - |) in - (* TODO statement *) - - -Definition dup_n : M unit := + |) 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. @@ -88,20 +98,26 @@ Definition dup_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - let* data_to_duplicate := (* TODO expression *) in - do* stack.["push"] (| - evm.["stack"], - data_to_duplicate - |) 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 : M unit := +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. @@ -120,11 +136,15 @@ Definition swap_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - (* 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/storage.v b/coq/ethereum/cancun/vm/instructions/storage.v index 8e44bdd9db..10d072cd60 100644 --- a/coq/ethereum/cancun/vm/instructions/storage.v +++ b/coq/ethereum/cancun/vm/instructions/storage.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Storage Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,12 +14,13 @@ Implementations of the EVM storage related instructions. *) Require ethereum_types.numeric. -Require cancun.state. -Require cancun.vm.exceptions. -Require cancun.vm.gas. -Require cancun.vm.stack. +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 : M unit := +Definition sload (evm : Evm) : M unit := (* Loads to the stack, the value corresponding to a certain key from the storage of the current account. @@ -29,25 +31,33 @@ Definition sload : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in + |) in + ]] in (* TODO statement *) - let* value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) - - -Definition sstore : M unit := + 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. @@ -57,46 +67,60 @@ Definition sstore : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in + 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 *) - let* original_value := state.get_storage_original (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - let* current_value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - let* gas_cost := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in + M.get_local ~(| "gas_cost" |) + |) ]] in (* TODO statement *) - do* state.set_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key, - new_value - |) in - (* TODO statement *) - - -Definition tload : M unit := + 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. @@ -105,28 +129,36 @@ Definition tload : M unit := evm : The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - do* gas.charge_gas (| + 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 - let* value := state.get_transient_storage (| - evm.["env"].["transient_storage"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) - - -Definition tstore : M unit := + |) ]] 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 @@ -134,24 +166,32 @@ Definition tstore : M unit := evm : The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["env"].["transient_storage"], - evm.["message"].["current_target"], - key, - new_value - |) in + |) ]] 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.v b/coq/ethereum/cancun/vm/instructions/system.v index d7e376c6d5..69b4be5a7d 100644 --- a/coq/ethereum/cancun/vm/instructions/system.v +++ b/coq/ethereum/cancun/vm/instructions/system.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) System Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,58 +16,73 @@ Implementations of the EVM system related instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require cancun.fork_types. -Require cancun.state. -Require cancun.utils.address. -Require cancun.vm.exceptions. -Require cancun.vm.gas. -Require cancun.vm.memory. -Require cancun.vm.stack. - -Definition generic_create : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) in + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_start_position, + memory_size + |) in + ]] in (* TODO statement *) - do* evm.["accessed_addresses"].["add"] (| + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "add" |) ~(| contract_address - |) in - let* create_message_gas := gas.max_message_call_gas (| - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |) - |) in - (* TODO statement *) + |) ]] 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 *) - let* sender_address := evm.["message"].["current_target"] in - let* sender := state.get_account (| - evm.["env"].["state"], - sender_address - |) in - (* TODO statement *) - (* TODO statement *) - do* state.increment_nonce (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |) in - let* child_message := Message (| - - |) in - let* child_evm := process_create_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - - -Definition create : M unit := + 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. @@ -75,48 +91,66 @@ Definition create : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* init_code_gas := gas.init_code_cost (| - ethereum_types.numeric.Uint (| - memory_size - |) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_contract_address (| - evm.["message"].["current_target"], - state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["nonce"] - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size, - init_code_gas - |) in - (* TODO statement *) - + 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 : M unit := +Definition create2 (evm : Evm) : M unit := (* Creates a new account with associated code. @@ -128,56 +162,78 @@ Definition create2 : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* salt := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* call_data_words := (* TODO expression *) in - let* init_code_gas := gas.init_code_cost (| - ethereum_types.numeric.Uint (| - memory_size - |) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_create2_contract_address (| - evm.["message"].["current_target"], - salt, - memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size, - init_code_gas - |) in - (* TODO statement *) - + 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_ : M unit := +Definition return_ (evm : Evm) : M unit := (* Halts execution returning output data. @@ -186,66 +242,84 @@ Definition return_ : M unit := evm : The current EVM frame. *) - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) + |) ]] 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 : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_input_start_position, - memory_input_size - |) in - let* code := state.get_account (| - evm.["env"].["state"], - code_address - |).["code"] in - let* child_message := Message (| - - |) in - let* child_evm := process_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - let* actual_output_size := min (| - memory_output_size, - ethereum_types.numeric.U256 (| - len (| - child_evm.["output"] + 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 - do* memory.memory_write (| - evm.["memory"], + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), memory_output_start_position, (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition call : M unit := +Definition call (evm : Evm) : M unit := (* Message-call into an account. @@ -254,62 +328,92 @@ Definition call : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* create_gas_cost := (* TODO expression *) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in + |) ]] in (* TODO statement *) - (* 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 : M unit := +Definition callcode (evm : Evm) : M unit := (* Message-call into this account with alternative account’s code. @@ -318,61 +422,91 @@ Definition callcode : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* to := evm.["message"].["current_target"] in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) - (* TODO statement *) - + |) ]] 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 : M unit := +Definition selfdestruct (evm : Evm) : M unit := (* Halt execution and register account for later deletion. @@ -381,37 +515,45 @@ Definition selfdestruct : M unit := evm : The current EVM frame. *) - let* beneficiary := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* gas_cost := gas.GAS_SELF_DESTRUCT in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - (* TODO statement *) - let* originator := evm.["message"].["current_target"] in - let* originator_balance := state.get_account (| - evm.["env"].["state"], - originator - |).["balance"] in - do* state.move_ether (| - evm.["env"].["state"], - originator, - beneficiary, - originator_balance - |) in + 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 : M unit := +Definition delegatecall (evm : Evm) : M unit := (* Message-call into an account. @@ -420,67 +562,89 @@ Definition delegatecall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - access_gas_cost - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - evm.["message"].["value"], - evm.["message"].["caller"], - evm.["message"].["current_target"], - code_address, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition staticcall (evm : Evm) : M unit := (* Message-call into an account. @@ -489,69 +653,91 @@ Definition staticcall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - access_gas_cost - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - ethereum_types.numeric.U256 (| - (* TODO expression *) + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 |), - evm.["message"].["current_target"], - to, - to, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +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 @@ -560,27 +746,37 @@ Definition revert : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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, - extend_memory.["cost"] - |) in - (* TODO statement *) - let* output := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in + 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.v b/coq/ethereum/cancun/vm/interpreter.v index e84223f754..8f59b48949 100644 --- a/coq/ethereum/cancun/vm/interpreter.v +++ b/coq/ethereum/cancun/vm/interpreter.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Interpreter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +18,18 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.trace. -Require cancun.blocks. -Require cancun.fork_types. -Require cancun.state. -Require cancun.vm. -Require cancun.vm.gas. -Require cancun.vm.precompiled_contracts.mapping. -Require cancun.vm.exceptions. -Require cancun.vm.instructions. -Require cancun.vm.runtime. - -Definition process_message_call : M unit := +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`. @@ -47,19 +49,21 @@ Definition process_message_call : M unit := *) (* TODO statement *) (* TODO statement *) - let* tx_end := ethereum.trace.TransactionEnd (| - (* TODO expression *), - evm.["output"], - evm.["error"] - |) in - do* ethereum.trace.evm_trace (| - evm, - tx_end - |) in + 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 : M unit := +Definition process_create_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -75,31 +79,33 @@ Definition process_create_message : M unit := evm: :py:class:`~ethereum.cancun.vm.Evm` Items containing execution specific objects. *) - do* state.begin_transaction (| - env.["state"], - env.["transient_storage"] - |) in - do* state.destroy_storage (| - env.["state"], - message.["current_target"] - |) in - do* state.mark_account_created (| - env.["state"], - message.["current_target"] - |) in - do* state.increment_nonce (| - env.["state"], - message.["current_target"] - |) in - let* evm := process_message (| - message, - env - |) in + 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 : M unit := +Definition process_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -116,24 +122,26 @@ Definition process_message : M unit := Items containing execution specific objects *) (* TODO statement *) - do* state.begin_transaction (| - env.["state"], - env.["transient_storage"] - |) in - do* state.touch_account (| - env.["state"], - message.["current_target"] - |) in + 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 *) - let* evm := execute_code (| - message, - env - |) in + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition execute_code : M unit := +Definition execute_code (message : Message) (env : Environment) : M Evm := (* Executes bytecode present in the `message`. @@ -149,13 +157,19 @@ Definition execute_code : M unit := evm: `ethereum.vm.EVM` Items containing execution specific objects *) - let* code := message.["code"] in - let* valid_jump_destinations := runtime.get_valid_jump_destinations (| - code - |) in - let* evm := Evm (| - - |) in + 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.v b/coq/ethereum/cancun/vm/memory.v index 94b6a44639..88b516318f 100644 --- a/coq/ethereum/cancun/vm/memory.v +++ b/coq/ethereum/cancun/vm/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.byte. -Definition memory_write : M unit := +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := (* Writes to memory. @@ -30,9 +31,9 @@ Definition memory_write : M unit := Data to write to memory. *) (* TODO assignment *) + M.pure tt. - -Definition memory_read_bytes : M unit := +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := (* Read bytes from memory. @@ -51,9 +52,9 @@ Definition memory_read_bytes : M unit := Data read from memory. *) (* TODO statement *) + M.pure tt. - -Definition buffer_read : M unit := +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := (* Read bytes from a buffer. Padding with zeros if necessary. @@ -72,4 +73,4 @@ Definition buffer_read : M unit := Data read from memory. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/__init__.v b/coq/ethereum/cancun/vm/precompiled_contracts/__init__.v index 9d793f6554..f2700ca5f5 100644 --- a/coq/ethereum/cancun/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/cancun/vm/precompiled_contracts/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,4 +14,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require cancun.utils.hexadecimal. +Require ethereum.cancun.utils.hexadecimal. diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/cancun/vm/precompiled_contracts/alt_bn128.v index d7cb159a53..c63955b3ff 100644 --- a/coq/ethereum/cancun/vm/precompiled_contracts/alt_bn128.v +++ b/coq/ethereum/cancun/vm/precompiled_contracts/alt_bn128.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,12 +15,12 @@ Implementation of the ALT_BN128 precompiled contracts. Require ethereum_types.numeric. Require ethereum.crypto.alt_bn128. -Require cancun.vm. -Require cancun.vm.gas. -Require cancun.vm.memory. -Require cancun.vm.exceptions. +Require ethereum.cancun.vm. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.memory. +Require ethereum.cancun.vm.exceptions. -Definition alt_bn128_add : M unit := +Definition alt_bn128_add (evm : Evm) : M unit := (* The ALT_BN128 addition precompiled contract. @@ -28,76 +29,96 @@ Definition alt_bn128_add : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* x1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x1_bytes - |) - |) in - let* y1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y1_bytes - |) - |) in + 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 *) - let* p := (* TODO expression *) in + do* M.assign "p" [[ + (* TODO expression *) in + ]] in (* TODO assignment *) + M.pure tt. - -Definition alt_bn128_mul : M unit := +Definition alt_bn128_mul (evm : Evm) : M unit := (* The ALT_BN128 multiplication precompiled contract. @@ -106,63 +127,77 @@ Definition alt_bn128_mul : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* n := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) (* TODO statement *) - let* p := p0.["mul_by"] (| - n - |) in + 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 : M unit := +Definition alt_bn128_pairing_check (evm : Evm) : M unit := (* The ALT_BN128 pairing check precompiled contract. @@ -171,17 +206,21 @@ Definition alt_bn128_pairing_check : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 (| + ethereum_types.numeric.Uint ~(| (* TODO expression *) |) - |) in + |) ]] in (* TODO statement *) - let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/cancun/vm/precompiled_contracts/blake2f.v index 4808403d8f..86df041c8d 100644 --- a/coq/ethereum/cancun/vm/precompiled_contracts/blake2f.v +++ b/coq/ethereum/cancun/vm/precompiled_contracts/blake2f.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,11 @@ Implementation of the `Blake2` precompiled contract. *) Require ethereum.crypto.blake2. -Require cancun.vm. -Require cancun.vm.gas. -Require cancun.vm.exceptions. +Require ethereum.cancun.vm. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.exceptions. -Definition blake2f : M unit := +Definition blake2f (evm : Evm) : M unit := (* Writes the Blake2 hash to output. @@ -26,16 +27,20 @@ Definition blake2f : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in (* TODO statement *) - let* blake2b := ethereum.crypto.blake2.Blake2b (| + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| - |) in + |) in + ]] in (* TODO assignment *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, (* TODO expression *) - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/cancun/vm/precompiled_contracts/ecrecover.v index 3c1b792ab4..f3ea199717 100644 --- a/coq/ethereum/cancun/vm/precompiled_contracts/ecrecover.v +++ b/coq/ethereum/cancun/vm/precompiled_contracts/ecrecover.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,11 +17,11 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require cancun.vm. -Require cancun.vm.gas. -Require cancun.vm.memory. +Require ethereum.cancun.vm. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.memory. -Definition ecrecover : M unit := +Definition ecrecover (evm : Evm) : M unit := (* Decrypts the address using elliptic curve DSA recovery mechanism and writes the address to output. @@ -30,64 +31,80 @@ Definition ecrecover : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* message_hash_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* message_hash := ethereum.crypto.hash.Hash32 (| - message_hash_bytes - |) in - let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + ethereum_types.numeric.U256 ~(| + 32 |) - |) - |) in - let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 + ]] 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 *) - let* address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/cancun/vm/precompiled_contracts/identity.v index 3b7740c3da..6c3123d4ee 100644 --- a/coq/ethereum/cancun/vm/precompiled_contracts/identity.v +++ b/coq/ethereum/cancun/vm/precompiled_contracts/identity.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,10 @@ Implementation of the `IDENTITY` precompiled contract. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require cancun.vm. -Require cancun.vm.gas. +Require ethereum.cancun.vm. +Require ethereum.cancun.vm.gas. -Definition identity : M unit := +Definition identity (evm : Evm) : M unit := (* Writes the message data to output. @@ -26,11 +27,15 @@ Definition identity : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/mapping.v b/coq/ethereum/cancun/vm/precompiled_contracts/mapping.v index 7dd353ccee..98fd18dbd7 100644 --- a/coq/ethereum/cancun/vm/precompiled_contracts/mapping.v +++ b/coq/ethereum/cancun/vm/precompiled_contracts/mapping.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,12 +14,13 @@ Mapping of precompiled contracts their implementations. *) Require typing. -Require cancun.fork_types. -Require cancun.vm.precompiled_contracts.alt_bn128. -Require cancun.vm.precompiled_contracts.blake2f. -Require cancun.vm.precompiled_contracts.ecrecover. -Require cancun.vm.precompiled_contracts.identity. -Require cancun.vm.precompiled_contracts.modexp. -Require cancun.vm.precompiled_contracts.point_evaluation. -Require cancun.vm.precompiled_contracts.ripemd160. -Require cancun.vm.precompiled_contracts.sha256. +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.v b/coq/ethereum/cancun/vm/precompiled_contracts/modexp.v index e885e634b8..ee22d9d2e5 100644 --- a/coq/ethereum/cancun/vm/precompiled_contracts/modexp.v +++ b/coq/ethereum/cancun/vm/precompiled_contracts/modexp.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,100 +15,120 @@ Implementation of the `MODEXP` precompiled contract. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require cancun.vm. -Require cancun.vm.gas. -Require cancun.vm.memory. +Require ethereum.cancun.vm. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.memory. -Definition modexp : M unit := +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. *) - let* data := evm.["message"].["data"] in - let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) - |) in - let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 - let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* exp_start := (* TODO expression *) in - let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - min (| - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 |), - exp_length + ethereum_types.numeric.U256 ~(| + 32 + |) |) - |) - |) in - do* vm.gas.charge_gas (| + |) 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, - gas_cost (| - base_length, - modulus_length, - exp_length, - exp_head + 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 + |) ]] in (* TODO statement *) - let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - base_length - |) - |) in - let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - exp_length - |) - |) in - let* modulus_start := (* TODO expression *) in - let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - modulus_start, - modulus_length - |) - |) in + 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 : M unit := +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := (* Estimate the complexity of performing a modular exponentiation. @@ -126,19 +147,23 @@ Definition complexity : M unit := complexity : `Uint` Complexity of performing the operation. *) - let* max_length := max (| - ethereum_types.numeric.Uint (| - base_length - |), - ethereum_types.numeric.Uint (| - modulus_length - |) - |) in - let* words := (* TODO expression *) in + 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 : M unit := +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := (* Calculate the number of iterations required to perform a modular exponentiation. @@ -161,9 +186,9 @@ Definition iterations : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition gas_cost : M unit := +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. @@ -189,15 +214,23 @@ Definition gas_cost : M unit := gas_cost : `Uint` Gas required for performing the operation. *) - let* multiplication_complexity := complexity (| - base_length, - modulus_length - |) in - let* iteration_count := iterations (| - exponent_length, - exponent_head - |) in - let* cost := (* TODO expression *) in - (* TODO statement *) + 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.v b/coq/ethereum/cancun/vm/precompiled_contracts/point_evaluation.v index a26fdde533..089fae1b31 100644 --- a/coq/ethereum/cancun/vm/precompiled_contracts/point_evaluation.v +++ b/coq/ethereum/cancun/vm/precompiled_contracts/point_evaluation.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) POINT EVALUATION PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,11 @@ Implementation of the POINT EVALUATION precompiled contract. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.kzg. -Require cancun.vm. -Require cancun.vm.exceptions. -Require cancun.vm.gas. +Require ethereum.cancun.vm. +Require ethereum.cancun.vm.exceptions. +Require ethereum.cancun.vm.gas. -Definition point_evaluation : M unit := +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. @@ -30,27 +31,39 @@ Definition point_evaluation : M unit := The current EVM frame. *) - let* data := evm.["message"].["data"] in + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in (* TODO statement *) - let* versioned_hash := (* TODO expression *) in - let* z := ethereum_types.bytes.Bytes32 (| - (* TODO expression *) - |) in - let* y := ethereum_types.bytes.Bytes32 (| - (* TODO expression *) - |) in - let* commitment := ethereum.crypto.kzg.KZGCommitment (| - (* TODO expression *) - |) in - let* proof := ethereum_types.bytes.Bytes48 (| - (* TODO expression *) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/cancun/vm/precompiled_contracts/ripemd160.v index bc5e73dd3c..fe2c66bbe6 100644 --- a/coq/ethereum/cancun/vm/precompiled_contracts/ripemd160.v +++ b/coq/ethereum/cancun/vm/precompiled_contracts/ripemd160.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `RIPEMD160` precompiled contract. *) -Definition ripemd160 : M unit := +Definition ripemd160 (evm : Evm) : M unit := (* Writes the ripemd160 hash to output. @@ -22,21 +23,29 @@ Definition ripemd160 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 - let* hash_bytes := hashlib.["new"] (| - (* TODO expression *), - data - |).["digest"] (| - - |) in - let* padded_hash := left_pad_zero_bytes (| - hash_bytes, - (* TODO expression *) - |) in + |) ]] 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.v b/coq/ethereum/cancun/vm/precompiled_contracts/sha256.v index da6972d411..3ba3ffe7aa 100644 --- a/coq/ethereum/cancun/vm/precompiled_contracts/sha256.v +++ b/coq/ethereum/cancun/vm/precompiled_contracts/sha256.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `SHA256` precompiled contract. *) -Definition sha256 : M unit := +Definition sha256 (evm : Evm) : M unit := (* Writes the sha256 hash to output. @@ -22,11 +23,15 @@ Definition sha256 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/cancun/vm/runtime.v b/coq/ethereum/cancun/vm/runtime.v index 7ec918f688..877c7c9b74 100644 --- a/coq/ethereum/cancun/vm/runtime.v +++ b/coq/ethereum/cancun/vm/runtime.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Runtime Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Runtime related operations used while executing EVM code. Require typing. Require ethereum_types.numeric. -Require cancun.vm.instructions. +Require ethereum.cancun.vm.instructions. -Definition get_valid_jump_destinations : M unit := +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := (* Analyze the evm code to obtain the set of valid jump destinations. @@ -38,12 +39,16 @@ Definition get_valid_jump_destinations : M unit := valid_jump_destinations: `Set[Uint]` The set of valid jump destinations in the code. *) - let* valid_jump_destinations := set (| - - |) in - let* pc := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/cancun/vm/stack.v index 96481b4af1..eb255bec67 100644 --- a/coq/ethereum/cancun/vm/stack.v +++ b/coq/ethereum/cancun/vm/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Implementation of the stack operators for the EVM. Require typing. Require ethereum_types.numeric. -Require cancun.vm.exceptions. +Require ethereum.cancun.vm.exceptions. -Definition pop : M unit := +Definition pop (stack : (* TODO type *)) : M U256 := (* Pops the top item off of `stack`. @@ -33,9 +34,9 @@ Definition pop : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition push : M unit := +Definition push (stack : (* TODO type *)) (value : U256) : M unit := (* Pushes `value` onto `stack`. @@ -50,4 +51,4 @@ Definition push : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/constantinople/__init__.v b/coq/ethereum/constantinople/__init__.v index 440e1bea53..70fadd17f8 100644 --- a/coq/ethereum/constantinople/__init__.v +++ b/coq/ethereum/constantinople/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* The Constantinople fork reduces mining rewards, delays the difficulty bomb, and introduces new EVM instructions for logical shifts, counterfactual diff --git a/coq/ethereum/constantinople/blocks.v b/coq/ethereum/constantinople/blocks.v index b9f11c596c..304641fa9a 100644 --- a/coq/ethereum/constantinople/blocks.v +++ b/coq/ethereum/constantinople/blocks.v @@ -1,3 +1,4 @@ +(* 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 @@ -14,6 +15,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. -Require constantinople.fork_types. -Require constantinople.transactions. +Require ethereum.crypto.hash. +Require ethereum.constantinople.fork_types. +Require ethereum.constantinople.transactions. diff --git a/coq/ethereum/constantinople/bloom.v b/coq/ethereum/constantinople/bloom.v index fb43b89d06..5f84d0e4ec 100644 --- a/coq/ethereum/constantinople/bloom.v +++ b/coq/ethereum/constantinople/bloom.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Logs Bloom ^^^^^^^^^^^^^^^^^^^ @@ -19,10 +20,10 @@ eliminating blocks and receipts from their search. Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require constantinople.blocks. -Require constantinople.fork_types. +Require ethereum.constantinople.blocks. +Require ethereum.constantinople.fork_types. -Definition add_to_bloom : M unit := +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := (* Add a bloom entry to the bloom filter (`bloom`). @@ -37,13 +38,15 @@ Definition add_to_bloom : M unit := bloom_entry : An entry which is to be added to bloom filter. *) - let* hash := ethereum.crypto.hash.keccak256 (| - bloom_entry - |) in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition logs_bloom : M unit := +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := (* Obtain the logs bloom from a list of log entries. @@ -63,4 +66,4 @@ Definition logs_bloom : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/constantinople/fork.v b/coq/ethereum/constantinople/fork.v index e1d424bb04..09b0d5a7c7 100644 --- a/coq/ethereum/constantinople/fork.v +++ b/coq/ethereum/constantinople/fork.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^ @@ -20,16 +21,18 @@ Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.ethash. Require ethereum.exceptions. -Require constantinople.blocks. -Require constantinople.bloom. -Require constantinople.fork_types. -Require constantinople.state. -Require constantinople.transactions. -Require constantinople.trie. -Require constantinople.utils.message. -Require constantinople.vm.interpreter. - -Definition apply_fork : M unit := +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. @@ -49,9 +52,9 @@ Definition apply_fork : M unit := Upgraded block chain object for this hard fork. *) (* TODO statement *) + M.pure tt. - -Definition get_last_256_block_hashes : M unit := +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. @@ -71,22 +74,28 @@ Definition get_last_256_block_hashes : M unit := recent_block_hashes : `List[Hash32]` Hashes of the recent 256 blocks in order of increasing block number. *) - let* recent_blocks := (* TODO expression *) in - (* TODO statement *) - let* recent_block_hashes := (* TODO expression *) in - (* TODO statement *) - let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *).["header"] - |) - |) in - do* recent_block_hashes.["append"] (| - most_recent_block_hash - |) in - (* TODO statement *) - - -Definition state_transition : M unit := + 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. @@ -108,42 +117,46 @@ Definition state_transition : M unit := block : Block to apply to `chain`. *) - let* parent_header := (* TODO expression *).["header"] in - do* validate_header (| - block.["header"], - parent_header - |) in - do* validate_ommers (| - block.["ommers"], - block.["header"], + 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 - let* apply_body_output := apply_body (| - chain.["state"], - get_last_256_block_hashes (| - chain - |), - block.["header"].["coinbase"], - block.["header"].["number"], - block.["header"].["gas_limit"], - block.["header"].["timestamp"], - block.["header"].["difficulty"], - block.["transactions"], - block.["ommers"], - chain.["chain_id"] - |) in + |) ]] 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* chain.["blocks"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| block - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition validate_header : M unit := +Definition validate_header (header : Header) (parent_header : Header) : M unit := (* Verifies a block header. @@ -161,31 +174,37 @@ Definition validate_header : M unit := parent_header : Parent Header of the header to check for correctness *) - let* parent_has_ommers := (* TODO expression *) in + do* M.assign "parent_has_ommers" [[ + (* TODO expression *) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* block_difficulty := calculate_block_difficulty (| - header.["number"], - header.["timestamp"], - parent_header.["timestamp"], - parent_header.["difficulty"], - parent_has_ommers - |) in + 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 *) - let* block_parent_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - parent_header - |) - |) in + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in (* TODO statement *) - do* validate_proof_of_work (| + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| header - |) in - + |) ]] in + M.pure tt. -Definition generate_header_hash_for_pow : M unit := +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. @@ -208,11 +227,13 @@ Definition generate_header_hash_for_pow : M unit := hash : `Hash32` The PoW valid rlp hash of the passed in header. *) - let* header_data_without_pow_artefacts := (* TODO expression *) in + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition validate_proof_of_work : M unit := +Definition validate_proof_of_work (header : Header) : M unit := (* Validates the Proof of Work constraints. @@ -227,19 +248,25 @@ Definition validate_proof_of_work : M unit := header : Header of interest. *) - let* header_hash := generate_header_hash_for_pow (| - header - |) in - let* cache := ethereum.ethash.generate_cache (| - header.["number"] - |) in + 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 *) - let* limit := (* TODO expression *) in + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition check_transaction : M unit := +Definition check_transaction (tx : Transaction) (gas_available : Uint) (chain_id : U64) : M Address := (* Check if the transaction is includable in the block. @@ -263,14 +290,16 @@ Definition check_transaction : M unit := If the transaction is not includable. *) (* TODO statement *) - let* sender_address := recover_sender (| - chain_id, - tx - |) in + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition make_receipt : M unit := +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. @@ -291,13 +320,15 @@ Definition make_receipt : M unit := receipt : The receipt for the transaction. *) - let* receipt := blocks.Receipt (| + do* M.assign "receipt" [[ + blocks.Receipt ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition apply_body : M unit := +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. @@ -338,25 +369,31 @@ Definition apply_body : M unit := apply_body_output : `ApplyBodyOutput` Output of applying the block body to the state. *) - let* gas_available := block_gas_limit in + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - do* pay_rewards (| + do* [[ M.get_local ~(| "pay_rewards" |) ~(| state, block_number, coinbase, ommers - |) in - let* block_gas_used := (* TODO expression *) in - let* block_logs_bloom := bloom.logs_bloom (| - block_logs - |) in - (* TODO statement *) - - -Definition validate_ommers : M unit := + |) ]] 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. @@ -378,23 +415,31 @@ Definition validate_ommers : M unit := chain : History and current state. *) - let* block_hash := rlp.["rlp_hash"] (| - block_header - |) in + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* ommers_hashes := (* TODO expression *) in + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* recent_canonical_blocks := (* TODO expression *) in - let* recent_canonical_block_hashes := (* TODO expression *) in + 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 : M unit := +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. @@ -420,21 +465,25 @@ Definition pay_rewards : M unit := ommers : List of ommers mentioned in the current block. *) - let* ommer_count := ethereum_types.numeric.U256 (| - len (| - ommers - |) - |) in - let* miner_reward := (* TODO expression *) in - do* state.create_ether (| + 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, - miner_reward - |) in + M.get_local ~(| "miner_reward" |) + |) ]] in (* TODO statement *) + M.pure tt. - -Definition process_transaction : M unit := +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := (* Execute a transaction against the provided environment. @@ -462,64 +511,92 @@ Definition process_transaction : M unit := Logs generated during execution. *) (* TODO statement *) - let* sender := env.["origin"] in - let* sender_account := state.get_account (| - env.["state"], - sender - |) in - let* gas_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* gas := (* TODO expression *) in - do* state.increment_nonce (| - env.["state"], - sender - |) in - let* sender_balance_after_gas_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - ethereum_types.numeric.U256 (| - sender_balance_after_gas_fee - |) - |) in - let* message := utils.message.prepare_message (| - sender, - tx.["to"], - tx.["value"], - tx.["data"], - gas, - env - |) in - let* output := vm.interpreter.process_message_call (| - message, - env - |) in - let* gas_used := (* TODO expression *) in - let* gas_refund := min (| - (* TODO expression *), - ethereum_types.numeric.Uint (| - output.["refund_counter"] + 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 - let* gas_refund_amount := (* TODO expression *) in - let* transaction_fee := (* TODO expression *) in - let* total_gas_used := (* TODO expression *) in - let* sender_balance_after_refund := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - sender_balance_after_refund - |) in - let* coinbase_balance_after_mining_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - - -Definition validate_transaction : M unit := + |) ]] 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. @@ -547,9 +624,9 @@ Definition validate_transaction : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition calculate_intrinsic_cost : M unit := +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := (* Calculates the gas that is charged before execution is started. @@ -572,13 +649,15 @@ Definition calculate_intrinsic_cost : M unit := verified : `ethereum.base_types.Uint` The intrinsic cost of the transaction. *) - let* data_cost := (* TODO expression *) in + do* M.assign "data_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition recover_sender : M unit := +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := (* Extracts the sender address from a transaction. @@ -605,9 +684,9 @@ Definition recover_sender : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_pre155 : M unit := +Definition signing_hash_pre155 (tx : Transaction) : M Hash32 := (* Compute the hash of a transaction used in a legacy (pre EIP 155) signature. @@ -622,9 +701,9 @@ Definition signing_hash_pre155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_155 : M unit := +Definition signing_hash_155 (tx : Transaction) (chain_id : U64) : M Hash32 := (* Compute the hash of a transaction used in a EIP 155 signature. @@ -641,9 +720,9 @@ Definition signing_hash_155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition compute_header_hash : M unit := +Definition compute_header_hash (header : Header) : M Hash32 := (* Computes the hash of a block header. @@ -676,9 +755,9 @@ Definition compute_header_hash : M unit := Hash of the header. *) (* TODO statement *) + M.pure tt. - -Definition check_gas_limit : M unit := +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := (* Validates the gas limit for a block. @@ -706,14 +785,16 @@ Definition check_gas_limit : M unit := check : `bool` True if gas limit constraints are satisfied, False otherwise. *) - let* max_adjustment_delta := (* TODO expression *) in + 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 : M unit := +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. @@ -752,9 +833,15 @@ Definition calculate_block_difficulty : M unit := difficulty : `ethereum.base_types.Uint` Computed difficulty for a block. *) - let* offset := (* TODO expression *) in - let* difficulty := (* TODO expression *) in - let* num_bomb_periods := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - + 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.v b/coq/ethereum/constantinople/fork_types.v index 14de99d5e5..d84cffdf45 100644 --- a/coq/ethereum/constantinople/fork_types.v +++ b/coq/ethereum/constantinople/fork_types.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Types ^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. +Require ethereum.__init__. +Require ethereum.crypto.hash. -Definition encode_account : M unit := +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := (* Encode `Account` dataclass. @@ -26,4 +28,4 @@ Definition encode_account : M unit := encoded without providing a storage root. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/constantinople/state.v b/coq/ethereum/constantinople/state.v index bbfa643372..c860ca3d14 100644 --- a/coq/ethereum/constantinople/state.v +++ b/coq/ethereum/constantinople/state.v @@ -1,3 +1,4 @@ +(* Generated *) (* State ^^^^^ @@ -22,10 +23,10 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require constantinople.fork_types. -Require constantinople.trie. +Require ethereum.constantinople.fork_types. +Require ethereum.constantinople.trie. -Definition close_state : M unit := +Definition close_state (state : State) : M unit := (* Free resources held by the state. Used by optimized implementations to release file descriptors. @@ -33,9 +34,9 @@ Definition close_state : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition begin_transaction : M unit := +Definition begin_transaction (state : State) : M unit := (* Start a state transaction. @@ -47,12 +48,12 @@ Definition begin_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition commit_transaction : M unit := +Definition commit_transaction (state : State) : M unit := (* Commit a state transaction. @@ -61,12 +62,12 @@ Definition commit_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["pop"] (| - - |) in + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + |) ]] in + M.pure tt. -Definition rollback_transaction : M unit := +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. @@ -77,9 +78,9 @@ Definition rollback_transaction : M unit := The state. *) (* TODO assignment *) + M.pure tt. - -Definition get_account : M unit := +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. @@ -99,14 +100,16 @@ Definition get_account : M unit := account : `Account` Account at address. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition get_account_optional : M unit := +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. @@ -123,14 +126,16 @@ Definition get_account_optional : M unit := account : `Account` Account at address. *) - let* account := trie.trie_get (| - state.["_main_trie"], - address - |) in + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition set_account : M unit := +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()`). @@ -144,14 +149,14 @@ Definition set_account : M unit := account : `Account` Account to set at address. *) - do* trie.trie_set (| - state.["_main_trie"], + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), address, account - |) in - + |) ]] in + M.pure tt. -Definition destroy_account : M unit := +Definition destroy_account (state : State) (address : Address) : M unit := (* Completely remove the account at `address` and all of its storage. @@ -166,18 +171,18 @@ Definition destroy_account : M unit := address : `Address` Address of account to destroy. *) - do* destroy_storage (| + do* [[ M.get_local ~(| "destroy_storage" |) ~(| state, address - |) in - do* set_account (| + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - (* TODO expression *) - |) in - + tt + |) ]] in + M.pure tt. -Definition destroy_storage : M unit := +Definition destroy_storage (state : State) (address : Address) : M unit := (* Completely remove the storage at `address`. @@ -189,9 +194,9 @@ Definition destroy_storage : M unit := Address of account whose storage is to be deleted. *) (* TODO statement *) + M.pure tt. - -Definition get_storage : M unit := +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. @@ -210,19 +215,23 @@ Definition get_storage : M unit := value : `U256` Value at the key. *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition set_storage : M unit := +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. @@ -239,19 +248,21 @@ Definition set_storage : M unit := Value to set at the key. *) (* TODO statement *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - do* trie.trie_set (| - trie, + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), key, value - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition storage_root : M unit := +Definition storage_root (state : State) (address : Address) : M Root := (* Calculate the storage root of an account. @@ -269,9 +280,9 @@ Definition storage_root : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition state_root : M unit := +Definition state_root (state : State) : M Root := (* Calculate the state root. @@ -288,9 +299,9 @@ Definition state_root : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition account_exists : M unit := +Definition account_exists (state : State) (address : Address) : M bool := (* Checks if an account exists in the state trie @@ -307,9 +318,9 @@ Definition account_exists : M unit := True if account exists in the state trie, False otherwise *) (* TODO statement *) + M.pure tt. - -Definition account_has_code_or_nonce : M unit := +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := (* Checks if an account has non zero nonce or non empty code @@ -326,14 +337,16 @@ Definition account_has_code_or_nonce : M unit := True if if an account has non zero nonce or non empty code, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_empty : M unit := +Definition is_account_empty (state : State) (address : Address) : M bool := (* Checks if an account has zero nonce, empty code and zero balance. @@ -350,14 +363,16 @@ Definition is_account_empty : M unit := True if if an account has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition account_exists_and_is_empty : M unit := +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. @@ -375,14 +390,16 @@ Definition account_exists_and_is_empty : M unit := True if an account exists and has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_alive : M unit := +Definition is_account_alive (state : State) (address : Address) : M bool := (* Check whether is an account is both in the state and non empty. @@ -398,49 +415,51 @@ Definition is_account_alive : M unit := is_alive : `bool` True if the account is alive. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition modify_state : M unit := +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := (* Modify an `Account` in the `State`. *) - do* set_account (| + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - ethereum_types.frozen.modify (| - get_account (| + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| state, address |), f |) - |) in - + |) ]] in + M.pure tt. -Definition move_ether : M unit := +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := (* Move funds between accounts. *) (* TODO statement *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, sender_address, - reduce_sender_balance - |) in - do* modify_state (| + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| state, recipient_address, - increase_recipient_balance - |) in + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. - -Definition set_account_balance : M unit := +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := (* Sets the balance of an account. @@ -456,14 +475,14 @@ Definition set_account_balance : M unit := The amount that needs to set in balance. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - set_balance - |) in - + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. -Definition touch_account : M unit := +Definition touch_account (state : State) (address : Address) : M unit := (* Initializes an account to state. @@ -476,9 +495,9 @@ Definition touch_account : M unit := The address of the account that need to initialised. *) (* TODO statement *) + M.pure tt. - -Definition increment_nonce : M unit := +Definition increment_nonce (state : State) (address : Address) : M unit := (* Increments the nonce of an account. @@ -491,14 +510,14 @@ Definition increment_nonce : M unit := Address of the account whose nonce needs to be incremented. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_nonce - |) in - + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. -Definition set_code : M unit := +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := (* Sets Account code. @@ -514,14 +533,14 @@ Definition set_code : M unit := The bytecode that needs to be set. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - write_code - |) in + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. - -Definition create_ether : M unit := +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := (* Add newly created ether to an account. @@ -535,9 +554,9 @@ Definition create_ether : M unit := The amount of ether to be added to the account of interest. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_balance - |) in - + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. diff --git a/coq/ethereum/constantinople/transactions.v b/coq/ethereum/constantinople/transactions.v index f9651a485a..dd5bc0ca13 100644 --- a/coq/ethereum/constantinople/transactions.v +++ b/coq/ethereum/constantinople/transactions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, @@ -9,4 +10,4 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require constantinople.fork_types. +Require ethereum.constantinople.fork_types. diff --git a/coq/ethereum/constantinople/trie.v b/coq/ethereum/constantinople/trie.v index 548de91e1c..6b8953f256 100644 --- a/coq/ethereum/constantinople/trie.v +++ b/coq/ethereum/constantinople/trie.v @@ -1,3 +1,4 @@ +(* Generated *) (* State Trie ^^^^^^^^^^ @@ -14,7 +15,7 @@ The state trie is the structure responsible for storing *) -Definition encode_internal_node : M unit := +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 @@ -35,22 +36,24 @@ Definition encode_internal_node : M unit := *) (* TODO statement *) (* TODO statement *) - let* encoded := rlp.["encode"] (| - unencoded - |) in + 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 : M unit := +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 : M unit := +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. @@ -66,9 +69,9 @@ Definition copy_trie : M unit := A copy of the trie. *) (* TODO statement *) + M.pure tt. - -Definition trie_set : M unit := +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := (* Stores an item in a Merkle Trie. @@ -85,9 +88,9 @@ Definition trie_set : M unit := Node to insert at `key`. *) (* TODO statement *) + M.pure tt. - -Definition trie_get : M unit := +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := (* Gets an item from the Merkle Trie. @@ -106,17 +109,17 @@ Definition trie_get : M unit := Node at `key` in the trie. *) (* TODO statement *) + M.pure tt. - -Definition common_prefix_length : M unit := +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 : M unit := +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := (* Compresses nibble-list into a standard byte array with a flag. @@ -150,14 +153,16 @@ Definition nibble_list_to_compact : M unit := compressed : `bytearray` Compact byte array. *) - let* compact := bytearray (| + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition bytes_to_nibble_list : M unit := +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := (* Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). @@ -171,14 +176,16 @@ Definition bytes_to_nibble_list : M unit := nibble_list : `Bytes` The `Bytes` in nibble-list format. *) - let* nibble_list := bytearray (| - (* TODO expression *) - |) in + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _prepare_trie : M unit := +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. @@ -199,9 +206,9 @@ Definition _prepare_trie : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition root : M unit := +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := (* Computes the root of a modified merkle patricia trie (MPT). @@ -219,22 +226,26 @@ Definition root : M unit := root : `.fork_types.Root` MPT root of the underlying key-value pairs. *) - let* obj := _prepare_trie (| - trie, - get_storage_root - |) in - let* root_node := encode_internal_node (| - patricialize (| - obj, - Uint (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) + M.pure tt. - -Definition patricialize : M unit := +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := (* Structural composition function. @@ -254,21 +265,29 @@ Definition patricialize : M unit := Root node of `obj`. *) (* TODO statement *) - let* arbitrary_key := next (| - iter (| - obj - |) - |) in + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in (* TODO statement *) - let* substring := (* TODO expression *) in - let* prefix_length := len (| - substring - |) in + 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 *) - let* value := (* TODO expression *) in + do* M.assign "value" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/constantinople/utils/__init__.v b/coq/ethereum/constantinople/utils/__init__.v index beff4482b1..7f30fe939b 100644 --- a/coq/ethereum/constantinople/utils/__init__.v +++ b/coq/ethereum/constantinople/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions unique to this particular fork. *) diff --git a/coq/ethereum/constantinople/utils/address.v b/coq/ethereum/constantinople/utils/address.v index da7da274c1..4cd9e16ff2 100644 --- a/coq/ethereum/constantinople/utils/address.v +++ b/coq/ethereum/constantinople/utils/address.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,9 +19,10 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require constantinople.fork_types. +Require ethereum.__init__. +Require ethereum.constantinople.fork_types. -Definition to_address : M unit := +Definition to_address (data : (* TODO type *)) : M Address := (* Convert a Uint or U256 value to a valid address (20 bytes). @@ -35,9 +37,9 @@ Definition to_address : M unit := The obtained address. *) (* TODO statement *) + M.pure tt. - -Definition compute_contract_address : M unit := +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := (* Computes address of the new account that needs to be created. @@ -54,20 +56,26 @@ Definition compute_contract_address : M unit := address: `Address` The computed address of the new account. *) - let* computed_address := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *) - |) - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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 : M unit := +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. @@ -86,14 +94,22 @@ Definition compute_create2_contract_address : M unit := address: `ethereum.constantinople.fork_types.Address` The computed address of the new account. *) - let* preimage := (* TODO expression *) in - let* computed_address := ethereum.crypto.hash.keccak256 (| - preimage - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/constantinople/utils/hexadecimal.v index bc629eb420..98728344f9 100644 --- a/coq/ethereum/constantinople/utils/hexadecimal.v +++ b/coq/ethereum/constantinople/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Constantinople types. *) Require ethereum.utils.hexadecimal. -Require constantinople.fork_types. +Require ethereum.constantinople.fork_types. -Definition hex_to_root : M unit := +Definition hex_to_root (hex_string : str) : M Root := (* Convert hex string to trie root. @@ -31,9 +32,9 @@ Definition hex_to_root : M unit := Trie root obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bloom : M unit := +Definition hex_to_bloom (hex_string : str) : M Bloom := (* Convert hex string to bloom. @@ -48,9 +49,9 @@ Definition hex_to_bloom : M unit := Bloom obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_address : M unit := +Definition hex_to_address (hex_string : str) : M Address := (* Convert hex string to Address (20 bytes). @@ -65,4 +66,4 @@ Definition hex_to_address : M unit := The address obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/constantinople/utils/message.v b/coq/ethereum/constantinople/utils/message.v index c3cd234a4f..e5fe6abc91 100644 --- a/coq/ethereum/constantinople/utils/message.v +++ b/coq/ethereum/constantinople/utils/message.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For The Message Data-structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,12 +17,12 @@ specification. Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require constantinople.fork_types. -Require constantinople.state. -Require constantinople.vm. -Require constantinople.utils.address. +Require ethereum.constantinople.fork_types. +Require ethereum.constantinople.state. +Require ethereum.constantinople.vm. +Require ethereum.constantinople.utils.address. -Definition prepare_message : M unit := +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. @@ -56,4 +57,4 @@ Definition prepare_message : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/__init__.v b/coq/ethereum/constantinople/vm/__init__.v index 9cb6aadbae..23d6c2baca 100644 --- a/coq/ethereum/constantinople/vm/__init__.v +++ b/coq/ethereum/constantinople/vm/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,12 +19,12 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require constantinople.blocks. -Require constantinople.fork_types. -Require constantinople.state. -Require constantinople.vm.precompiled_contracts. +Require ethereum.constantinople.blocks. +Require ethereum.constantinople.fork_types. +Require ethereum.constantinople.state. +Require ethereum.constantinople.vm.precompiled_contracts. -Definition incorporate_child_on_success : M unit := +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of a successful `child_evm` into the parent `evm`. @@ -34,19 +35,25 @@ Definition incorporate_child_on_success : M unit := 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 *) - (* TODO statement *) - (* TODO statement *) - do* evm.["accounts_to_delete"].["update"] (| - child_evm.["accounts_to_delete"] - |) in - do* evm.["touched_accounts"].["update"] (| - child_evm.["touched_accounts"] - |) in - (* TODO statement *) + M.pure tt. - -Definition incorporate_child_on_error : M unit := +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. @@ -59,5 +66,7 @@ Definition incorporate_child_on_error : M unit := *) (* TODO statement *) (* 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.v b/coq/ethereum/constantinople/vm/exceptions.v index 1784494410..47e26555d5 100644 --- a/coq/ethereum/constantinople/vm/exceptions.v +++ b/coq/ethereum/constantinople/vm/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Exceptions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/constantinople/vm/gas.v b/coq/ethereum/constantinople/vm/gas.v index 1f6a2740bc..2ad12ff450 100644 --- a/coq/ethereum/constantinople/vm/gas.v +++ b/coq/ethereum/constantinople/vm/gas.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Gas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,9 +18,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.trace. Require ethereum.utils.numeric. -Require constantinople.vm.exceptions. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.exceptions. -Definition charge_gas : M unit := +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := (* Subtracts `amount` from `evm.gas_left`. @@ -31,18 +33,18 @@ Definition charge_gas : M unit := The amount of gas the current operation requires. *) - do* ethereum.trace.evm_trace (| + do* [[ ethereum.trace.evm_trace ~(| evm, - ethereum.trace.GasAndRefund (| - int (| + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| amount |) |) - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_memory_gas_cost : M unit := +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, @@ -58,14 +60,22 @@ Definition calculate_memory_gas_cost : M unit := total_gas_cost : `ethereum.base_types.Uint` The gas cost for storing data in memory. *) - let* size_in_words := (* TODO expression *) in - let* linear_cost := (* TODO expression *) in - let* quadratic_cost := (* TODO expression *) in - let* total_gas_cost := (* TODO expression *) in + 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 : M unit := +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := (* Calculates the gas amount to extend memory @@ -81,22 +91,28 @@ Definition calculate_gas_extend_memory : M unit := ------- extend_memory: `ExtendMemory` *) - let* size_to_extend := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* to_be_paid := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* current_size := ethereum_types.numeric.Uint (| - len (| - memory - |) - |) in + 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 : M unit := +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. @@ -122,18 +138,22 @@ Definition calculate_message_call_gas : M unit := ------- message_call_gas: `MessageCallGas` *) - let* call_stipend := (* TODO expression *) in + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* gas := min (| - gas, - max_message_call_gas (| - (* TODO expression *) - |) - |) in + 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 : M unit := +Definition max_message_call_gas (gas : Uint) : M Uint := (* Calculates the maximum gas that is allowed for making a message call @@ -148,4 +168,4 @@ Definition max_message_call_gas : M unit := The maximum gas allowed for making the message-call. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/instructions/__init__.v b/coq/ethereum/constantinople/vm/instructions/__init__.v index b36b1ebfef..cbd7e7e63a 100644 --- a/coq/ethereum/constantinople/vm/instructions/__init__.v +++ b/coq/ethereum/constantinople/vm/instructions/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* EVM Instruction Encoding (Opcodes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/constantinople/vm/instructions/arithmetic.v b/coq/ethereum/constantinople/vm/instructions/arithmetic.v index d11bf62de0..d44c4fba13 100644 --- a/coq/ethereum/constantinople/vm/instructions/arithmetic.v +++ b/coq/ethereum/constantinople/vm/instructions/arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,11 @@ Implementations of the EVM Arithmetic instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require constantinople.vm.gas. -Require constantinople.vm.stack. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.stack. -Definition add : M unit := +Definition add (evm : Evm) : M unit := (* Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -28,27 +30,37 @@ Definition add : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_add"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sub (evm : Evm) : M unit := (* Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -59,27 +71,37 @@ Definition sub : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_sub"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mul (evm : Evm) : M unit := (* Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -90,27 +112,37 @@ Definition mul : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_mul"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition div (evm : Evm) : M unit := (* Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -121,25 +153,33 @@ Definition div : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |) in - let* divisor := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - quotient - |) 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 : M unit := +Definition sdiv (evm : Evm) : M unit := (* Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -150,31 +190,39 @@ Definition sdiv : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* divisor := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - quotient + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mod : M unit := +Definition mod (evm : Evm) : M unit := (* Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -185,25 +233,33 @@ Definition mod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - remainder - |) in + |) ]] 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 : M unit := +Definition smod (evm : Evm) : M unit := (* Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -214,31 +270,39 @@ Definition smod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* y := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - remainder + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition addmod : M unit := +Definition addmod (evm : Evm) : M unit := (* Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -249,34 +313,44 @@ Definition addmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +Definition mulmod (evm : Evm) : M unit := (* Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -287,34 +361,44 @@ Definition mulmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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 : M unit := +Definition exp (evm : Evm) : M unit := (* Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -325,39 +409,53 @@ Definition exp : M unit := The current EVM frame. *) - let* base := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent_bits := exponent.["bit_length"] (| - - |) in - let* exponent_bytes := (* TODO expression *) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - pow (| - base, - exponent, - (* 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 - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition signextend : M unit := +Definition signextend (evm : Evm) : M unit := (* Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -368,20 +466,28 @@ Definition signextend : M unit := The current EVM frame. *) - let* byte_num := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/constantinople/vm/instructions/bitwise.v index b932c046a2..f827d32b35 100644 --- a/coq/ethereum/constantinople/vm/instructions/bitwise.v +++ b/coq/ethereum/constantinople/vm/instructions/bitwise.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Bitwise Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM bitwise instructions. *) Require ethereum_types.numeric. -Require constantinople.vm.gas. -Require constantinople.vm.stack. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.stack. -Definition bitwise_and : M unit := +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. @@ -27,24 +29,32 @@ Definition bitwise_and : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_or : M unit := +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. @@ -55,24 +65,32 @@ Definition bitwise_or : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_xor : M unit := +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. @@ -83,24 +101,32 @@ Definition bitwise_xor : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_not : M unit := +Definition bitwise_not (evm : Evm) : M unit := (* Bitwise NOT operation of the top element of the stack. Pushes the result back on the stack. @@ -111,21 +137,27 @@ Definition bitwise_not : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition get_byte : M unit := +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 @@ -137,25 +169,33 @@ Definition get_byte : M unit := The current EVM frame. *) - let* byte_index := stack.pop (| - evm.["stack"] - |) in - let* word := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -164,29 +204,37 @@ Definition bitwise_shl : M unit := evm : The current EVM frame. *) - let* shift := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -195,25 +243,33 @@ Definition bitwise_shr : M unit := evm : The current EVM frame. *) - let* shift := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -222,24 +278,32 @@ Definition bitwise_sar : M unit := evm : The current EVM frame. *) - let* shift := int (| - stack.pop (| - evm.["stack"] - |) - |) in - let* signed_value := stack.pop (| - evm.["stack"] - |).["to_signed"] (| + 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 - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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.v b/coq/ethereum/constantinople/vm/instructions/block.v index 477579821c..f4a4fea89b 100644 --- a/coq/ethereum/constantinople/vm/instructions/block.v +++ b/coq/ethereum/constantinople/vm/instructions/block.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Block Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM block instructions. *) Require ethereum_types.numeric. -Require constantinople.vm.gas. -Require constantinople.vm.stack. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.stack. -Definition block_hash : M unit := +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. @@ -27,27 +29,35 @@ Definition block_hash : M unit := The current EVM frame. *) - let* block_number := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* max_block_number := (* TODO expression *) in + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition coinbase : M unit := +Definition coinbase (evm : Evm) : M unit := (* Push the current block's beneficiary address (address of the block miner) onto the stack. @@ -62,20 +72,24 @@ Definition coinbase : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["coinbase"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition timestamp : M unit := +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. @@ -90,18 +104,22 @@ Definition timestamp : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["env"].["time"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition number (evm : Evm) : M unit := (* Push the current block's number onto the stack. @@ -115,20 +133,24 @@ Definition number : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["number"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition difficulty : M unit := +Definition difficulty (evm : Evm) : M unit := (* Push the current block's difficulty onto the stack. @@ -142,20 +164,24 @@ Definition difficulty : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["difficulty"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_limit : M unit := +Definition gas_limit (evm : Evm) : M unit := (* Push the current block's gas limit onto the stack. @@ -169,15 +195,19 @@ Definition gas_limit : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_limit"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/constantinople/vm/instructions/comparison.v index ba89c5e0d2..3ec417046c 100644 --- a/coq/ethereum/constantinople/vm/instructions/comparison.v +++ b/coq/ethereum/constantinople/vm/instructions/comparison.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Comparison Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM Comparison instructions. *) Require ethereum_types.numeric. -Require constantinople.vm.gas. -Require constantinople.vm.stack. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.stack. -Definition less_than : M unit := +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. @@ -27,27 +29,37 @@ Definition less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_less_than : M unit := + |) ]] 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. @@ -57,31 +69,41 @@ Definition signed_less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition greater_than : M unit := + |) ]] 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. @@ -92,27 +114,37 @@ Definition greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_greater_than : M unit := + |) ]] 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. @@ -122,31 +154,41 @@ Definition signed_greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition equal : M unit := + |) ]] 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. @@ -157,27 +199,37 @@ Definition equal : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition is_zero : M unit := + |) ]] 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. @@ -188,19 +240,27 @@ Definition is_zero : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/constantinople/vm/instructions/control_flow.v index 643fc57e22..0482031065 100644 --- a/coq/ethereum/constantinople/vm/instructions/control_flow.v +++ b/coq/ethereum/constantinople/vm/instructions/control_flow.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Control Flow Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM control flow instructions. *) Require ethereum_types.numeric. -Require constantinople.vm.gas. -Require constantinople.vm.exceptions. -Require constantinople.vm.stack. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.exceptions. +Require ethereum.constantinople.vm.stack. -Definition stop : M unit := +Definition stop (evm : Evm) : M unit := (* Stop further execution of EVM code. @@ -29,10 +31,14 @@ Definition stop : M unit := (* TODO statement *) (* TODO statement *) (* TODO assignment *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jump : M unit := +Definition jump (evm : Evm) : M unit := (* Alter the program counter to the location specified by the top of the stack. @@ -43,20 +49,22 @@ Definition jump : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition jumpi : M unit := +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 @@ -68,23 +76,27 @@ Definition jumpi : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* conditional_value := stack.pop (| - evm.["stack"] - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition pc : M unit := +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. @@ -96,20 +108,24 @@ Definition pc : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["pc"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_left : M unit := +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. @@ -121,20 +137,24 @@ Definition gas_left : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["gas_left"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jumpdest : M unit := +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 @@ -147,10 +167,14 @@ Definition jumpdest : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_JUMPDEST - |) in - (* TODO statement *) + |) ]] 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.v b/coq/ethereum/constantinople/vm/instructions/environment.v index 619b4d41e7..b58ea5f63c 100644 --- a/coq/ethereum/constantinople/vm/instructions/environment.v +++ b/coq/ethereum/constantinople/vm/instructions/environment.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,15 +16,16 @@ Implementations of the EVM environment related instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require constantinople.fork_types. -Require constantinople.state. -Require constantinople.utils.address. -Require constantinople.vm.memory. -Require constantinople.vm.exceptions. -Require constantinople.vm.gas. -Require constantinople.vm.stack. - -Definition address : M unit := +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. @@ -34,20 +36,24 @@ Definition address : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["current_target"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition balance : M unit := +Definition balance (evm : Evm) : M unit := (* Pushes the balance of the given account onto the stack. @@ -57,27 +63,35 @@ Definition balance : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* balance := state.get_account (| - evm.["env"].["state"], - address - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +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. @@ -89,20 +103,24 @@ Definition origin : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["origin"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition caller : M unit := +Definition caller (evm : Evm) : M unit := (* Pushes the address of the caller onto the stack. @@ -113,20 +131,24 @@ Definition caller : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["caller"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition callvalue : M unit := +Definition callvalue (evm : Evm) : M unit := (* Push the value (in wei) sent with the call onto the stack. @@ -137,18 +159,22 @@ Definition callvalue : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["message"].["value"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition calldataload (evm : Evm) : M unit := (* Push a word (32 bytes) of the input data belonging to the current environment onto the stack. @@ -159,30 +185,38 @@ Definition calldataload : M unit := The current EVM frame. *) - let* start_index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - start_index, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] 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* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - value + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 |) - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition calldatasize : M unit := +Definition calldatasize (evm : Evm) : M unit := (* Push the size of input data in current environment onto the stack. @@ -193,22 +227,26 @@ Definition calldatasize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["message"].["data"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition calldatacopy : M unit := +Definition calldatacopy (evm : Evm) : M unit := (* Copy a portion of the input data in current environment to memory. @@ -221,40 +259,60 @@ Definition calldatacopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* data_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - data_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition codesize (evm : Evm) : M unit := (* Push the size of code running in current environment onto the stack. @@ -265,22 +323,26 @@ Definition codesize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["code"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition codecopy : M unit := +Definition codecopy (evm : Evm) : M unit := (* Copy a portion of the code in current environment to memory. @@ -293,40 +355,60 @@ Definition codecopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["code"], - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition gasprice (evm : Evm) : M unit := (* Push the gas price used in current environment onto the stack. @@ -337,20 +419,24 @@ Definition gasprice : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_price"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition extcodesize : M unit := +Definition extcodesize (evm : Evm) : M unit := (* Push the code size of a given account onto the stack. @@ -360,31 +446,39 @@ Definition extcodesize : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* codesize := ethereum_types.numeric.U256 (| - len (| - state.get_account (| - evm.["env"].["state"], - address - |).["code"] + |) ]] 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 - do* stack.push (| - evm.["stack"], - codesize - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition extcodecopy : M unit := +Definition extcodecopy (evm : Evm) : M unit := (* Copy a portion of an account's code to memory. @@ -394,49 +488,73 @@ Definition extcodecopy : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* code := state.get_account (| - evm.["env"].["state"], - address - |).["code"] in - let* value := vm.memory.buffer_read (| - code, - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition returndatasize (evm : Evm) : M unit := (* Pushes the size of the return data buffer onto the stack. @@ -446,22 +564,26 @@ Definition returndatasize : M unit := The current EVM frame. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["return_data"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition returndatacopy : M unit := +Definition returndatacopy (evm : Evm) : M unit := (* Copies data from the return data buffer code to memory @@ -470,37 +592,57 @@ Definition returndatacopy : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* return_data_start_position := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) + |) ]] in (* TODO statement *) - let* value := (* TODO expression *) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) 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 : M unit := +Definition extcodehash (evm : Evm) : M unit := (* Returns the keccak256 hash of a contract’s bytecode Parameters @@ -508,23 +650,31 @@ Definition extcodehash : M unit := evm : The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* account := state.get_account (| - evm.["env"].["state"], - address - |) in - (* TODO statement *) - do* stack.push (| - evm.["stack"], - codehash - |) in + |) ]] 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.v b/coq/ethereum/constantinople/vm/instructions/keccak.v index 03d2ae2277..1479d39c1f 100644 --- a/coq/ethereum/constantinople/vm/instructions/keccak.v +++ b/coq/ethereum/constantinople/vm/instructions/keccak.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Keccak Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM keccak instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require constantinople.vm.gas. -Require constantinople.vm.memory. -Require constantinople.vm.stack. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.memory. +Require ethereum.constantinople.vm.stack. -Definition keccak : M unit := +Definition keccak (evm : Evm) : M unit := (* Pushes to the stack the Keccak-256 hash of a region of memory. @@ -32,36 +34,56 @@ Definition keccak : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* word_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in - let* hash := ethereum.crypto.hash.keccak256 (| - data - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/constantinople/vm/instructions/log.v index 08ad7b39f8..95129915df 100644 --- a/coq/ethereum/constantinople/vm/instructions/log.v +++ b/coq/ethereum/constantinople/vm/instructions/log.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Logging Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,13 +15,14 @@ Implementations of the EVM logging instructions. Require functools. Require ethereum_types.numeric. -Require constantinople.blocks. -Require constantinople.vm.exceptions. -Require constantinople.vm.gas. -Require constantinople.vm.memory. -Require constantinople.vm.stack. +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 : M unit := +Definition log_n (evm : Evm) (num_topics : U256) : M unit := (* Appends a log entry, having `num_topics` topics, to the evm logs. @@ -35,27 +37,43 @@ Definition log_n : M unit := The number of topics to be included in the log entry. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* topics := (* TODO expression *) in + 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 *) - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in (* TODO statement *) - let* log_entry := blocks.Log (| + do* M.assign "log_entry" [[ + blocks.Log ~(| - |) in + |) in + ]] in (* TODO assignment *) - (* 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/memory.v b/coq/ethereum/constantinople/vm/instructions/memory.v index 63b87f26a6..3f4f66b424 100644 --- a/coq/ethereum/constantinople/vm/instructions/memory.v +++ b/coq/ethereum/constantinople/vm/instructions/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM Memory instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require constantinople.vm.gas. -Require constantinople.vm.memory. -Require constantinople.vm.stack. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.memory. +Require ethereum.constantinople.vm.stack. -Definition mstore : M unit := +Definition mstore (evm : Evm) : M unit := (* Stores a word to memory. This also expands the memory, if the memory is @@ -30,32 +32,44 @@ Definition mstore : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* memory.memory_write (| - evm.["memory"], - start_position, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mstore8 (evm : Evm) : M unit := (* Stores a byte to memory. This also expands the memory, if the memory is @@ -67,33 +81,47 @@ Definition mstore8 : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ (* TODO expression *) - |) in - do* memory.memory_write (| - evm.["memory"], - start_position, - normalized_bytes_value - |) in - (* TODO statement *) - + ]] 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 : M unit := +Definition mload (evm : Evm) : M unit := (* Load word from memory. @@ -103,35 +131,47 @@ Definition mload : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.memory_read_bytes (| - evm.["memory"], - start_position, - ethereum_types.numeric.U256 (| - (* 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 - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition msize : M unit := +Definition msize (evm : Evm) : M unit := (* Push the size of active memory in bytes onto the stack. @@ -142,17 +182,21 @@ Definition msize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["memory"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/constantinople/vm/instructions/stack.v index a895f423d0..76776358a9 100644 --- a/coq/ethereum/constantinople/vm/instructions/stack.v +++ b/coq/ethereum/constantinople/vm/instructions/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM stack related instructions. Require functools. Require ethereum_types.numeric. -Require constantinople.vm.exceptions. -Require constantinople.vm.gas. -Require constantinople.vm.memory. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.exceptions. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.memory. -Definition pop : M unit := +Definition pop (evm : Evm) : M unit := (* Remove item from stack. @@ -28,18 +30,22 @@ Definition pop : M unit := The current EVM frame. *) - do* stack.["pop"] (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in + |) ]] in (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition push_n : M unit := +Definition push_n (evm : Evm) (num_bytes : int) : M unit := (* Pushes a N-byte immediate onto the stack. @@ -54,29 +60,33 @@ Definition push_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - evm.["code"], - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - num_bytes + |) ]] 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 - do* stack.["push"] (| - evm.["stack"], - data_to_push - |) in - (* TODO statement *) - - -Definition dup_n : M unit := + |) 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. @@ -91,20 +101,26 @@ Definition dup_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - let* data_to_duplicate := (* TODO expression *) in - do* stack.["push"] (| - evm.["stack"], - data_to_duplicate - |) 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 : M unit := +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. @@ -123,11 +139,15 @@ Definition swap_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - (* 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/storage.v b/coq/ethereum/constantinople/vm/instructions/storage.v index 0e5ea6a23e..c9dc5ee948 100644 --- a/coq/ethereum/constantinople/vm/instructions/storage.v +++ b/coq/ethereum/constantinople/vm/instructions/storage.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Storage Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,12 +14,13 @@ Implementations of the EVM storage related instructions. *) Require ethereum_types.numeric. -Require constantinople.state. -Require constantinople.vm.exceptions. -Require constantinople.vm.gas. -Require constantinople.vm.stack. +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 : M unit := +Definition sload (evm : Evm) : M unit := (* Loads to the stack, the value corresponding to a certain key from the storage of the current account. @@ -29,28 +31,36 @@ Definition sload : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_SLOAD - |) in - let* value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sstore (evm : Evm) : M unit := (* Stores a value at a certain key in the current context's storage. @@ -60,31 +70,41 @@ Definition sstore : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in - let* current_value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in + |) 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in + M.get_local ~(| "gas_cost" |) + |) ]] in (* TODO statement *) - do* state.set_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key, - new_value - |) 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.v b/coq/ethereum/constantinople/vm/instructions/system.v index adcc7f10c0..85d02f3e65 100644 --- a/coq/ethereum/constantinople/vm/instructions/system.v +++ b/coq/ethereum/constantinople/vm/instructions/system.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) System Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,54 +16,69 @@ Implementations of the EVM system related instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require constantinople.fork_types. -Require constantinople.state. -Require constantinople.utils.address. -Require constantinople.vm.exceptions. -Require constantinople.vm.gas. -Require constantinople.vm.memory. -Require constantinople.vm.stack. - -Definition generic_create : M unit := +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 *) - let* create_message_gas := gas.max_message_call_gas (| - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |) - |) in - (* 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 *) - let* sender_address := evm.["message"].["current_target"] in - let* sender := state.get_account (| - evm.["env"].["state"], - sender_address - |) in - (* TODO statement *) - (* TODO statement *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) in - do* state.increment_nonce (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |) in - let* child_message := Message (| - - |) in - let* child_evm := process_create_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - - -Definition create : M unit := + 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. @@ -71,42 +87,58 @@ Definition create : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_contract_address (| - evm.["message"].["current_target"], - state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["nonce"] - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition create2 (evm : Evm) : M unit := (* Creates a new account with associated code. @@ -118,50 +150,70 @@ Definition create2 : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* salt := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* call_data_words := (* TODO expression *) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_create2_contract_address (| - evm.["message"].["current_target"], - salt, - memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size - |) in - (* TODO statement *) - + 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_ : M unit := +Definition return_ (evm : Evm) : M unit := (* Halts execution returning output data. @@ -170,66 +222,84 @@ Definition return_ : M unit := evm : The current EVM frame. *) - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) + |) ]] 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 : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_input_start_position, - memory_input_size - |) in - let* code := state.get_account (| - evm.["env"].["state"], - code_address - |).["code"] in - let* child_message := Message (| - - |) in - let* child_evm := process_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - let* actual_output_size := min (| - memory_output_size, - ethereum_types.numeric.U256 (| - len (| - child_evm.["output"] + 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 - do* memory.memory_write (| - evm.["memory"], + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), memory_output_start_position, (* TODO expression *) - |) in + |) ]] in + M.pure tt. - -Definition call : M unit := +Definition call (evm : Evm) : M unit := (* Message-call into an account. @@ -238,61 +308,91 @@ Definition call : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* create_gas_cost := (* TODO expression *) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) - (* 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 : M unit := +Definition callcode (evm : Evm) : M unit := (* Message-call into this account with alternative account’s code. @@ -301,60 +401,90 @@ Definition callcode : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* to := evm.["message"].["current_target"] in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) - (* TODO statement *) - + |) ]] 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 : M unit := +Definition selfdestruct (evm : Evm) : M unit := (* Halt execution and register account for later deletion. @@ -363,52 +493,66 @@ Definition selfdestruct : M unit := evm : The current EVM frame. *) - let* beneficiary := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* gas_cost := gas.GAS_SELF_DESTRUCT in - (* TODO statement *) - let* originator := evm.["message"].["current_target"] in - let* refunded_accounts := evm.["accounts_to_delete"] in - let* parent_evm := evm.["message"].["parent_evm"] in - (* TODO statement *) - (* TODO statement *) - do* gas.charge_gas (| + 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, - gas_cost - |) in - (* TODO statement *) - let* beneficiary_balance := state.get_account (| - evm.["env"].["state"], - beneficiary - |).["balance"] in - let* originator_balance := state.get_account (| - evm.["env"].["state"], - originator - |).["balance"] in - do* state.set_account_balance (| - evm.["env"].["state"], - beneficiary, + 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 (| - evm.["env"].["state"], - originator, - ethereum_types.numeric.U256 (| - (* 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* evm.["accounts_to_delete"].["add"] (| - originator - |) in + |) ]] 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 : M unit := +Definition delegatecall (evm : Evm) : M unit := (* Message-call into an account. @@ -417,66 +561,88 @@ Definition delegatecall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - gas.GAS_CALL - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - evm.["message"].["value"], - evm.["message"].["caller"], - evm.["message"].["current_target"], - code_address, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition staticcall (evm : Evm) : M unit := (* Message-call into an account. @@ -485,68 +651,90 @@ Definition staticcall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - gas.GAS_CALL - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - ethereum_types.numeric.U256 (| - (* TODO expression *) + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 |), - evm.["message"].["current_target"], - to, - to, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +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 @@ -555,27 +743,37 @@ Definition revert : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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, - extend_memory.["cost"] - |) in - (* TODO statement *) - let* output := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in + 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.v b/coq/ethereum/constantinople/vm/interpreter.v index 45f11e60ca..cebe6f1599 100644 --- a/coq/ethereum/constantinople/vm/interpreter.v +++ b/coq/ethereum/constantinople/vm/interpreter.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Interpreter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +18,18 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.trace. -Require constantinople.blocks. -Require constantinople.fork_types. -Require constantinople.state. -Require constantinople.vm. -Require constantinople.vm.gas. -Require constantinople.vm.precompiled_contracts.mapping. -Require constantinople.vm.exceptions. -Require constantinople.vm.instructions. -Require constantinople.vm.runtime. - -Definition process_message_call : M unit := +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`. @@ -47,19 +49,21 @@ Definition process_message_call : M unit := *) (* TODO statement *) (* TODO statement *) - let* tx_end := ethereum.trace.TransactionEnd (| - (* TODO expression *), - evm.["output"], - evm.["error"] - |) in - do* ethereum.trace.evm_trace (| - evm, - tx_end - |) in + 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 : M unit := +Definition process_create_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -75,26 +79,28 @@ Definition process_create_message : M unit := evm: :py:class:`~ethereum.constantinople.vm.Evm` Items containing execution specific objects. *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.destroy_storage (| - env.["state"], - message.["current_target"] - |) in - do* state.increment_nonce (| - env.["state"], - message.["current_target"] - |) in - let* evm := process_message (| - message, - env - |) in + 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 : M unit := +Definition process_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -111,23 +117,25 @@ Definition process_message : M unit := Items containing execution specific objects *) (* TODO statement *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.touch_account (| - env.["state"], - message.["current_target"] - |) in + 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 *) - let* evm := execute_code (| - message, - env - |) in + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition execute_code : M unit := +Definition execute_code (message : Message) (env : Environment) : M Evm := (* Executes bytecode present in the `message`. @@ -143,13 +151,19 @@ Definition execute_code : M unit := evm: `ethereum.vm.EVM` Items containing execution specific objects *) - let* code := message.["code"] in - let* valid_jump_destinations := runtime.get_valid_jump_destinations (| - code - |) in - let* evm := Evm (| - - |) in + 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.v b/coq/ethereum/constantinople/vm/memory.v index 94b6a44639..88b516318f 100644 --- a/coq/ethereum/constantinople/vm/memory.v +++ b/coq/ethereum/constantinople/vm/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.byte. -Definition memory_write : M unit := +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := (* Writes to memory. @@ -30,9 +31,9 @@ Definition memory_write : M unit := Data to write to memory. *) (* TODO assignment *) + M.pure tt. - -Definition memory_read_bytes : M unit := +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := (* Read bytes from memory. @@ -51,9 +52,9 @@ Definition memory_read_bytes : M unit := Data read from memory. *) (* TODO statement *) + M.pure tt. - -Definition buffer_read : M unit := +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := (* Read bytes from a buffer. Padding with zeros if necessary. @@ -72,4 +73,4 @@ Definition buffer_read : M unit := Data read from memory. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/__init__.v b/coq/ethereum/constantinople/vm/precompiled_contracts/__init__.v index fa937a542c..312d23906c 100644 --- a/coq/ethereum/constantinople/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,4 +14,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require constantinople.utils.hexadecimal. +Require ethereum.constantinople.utils.hexadecimal. diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.v index 06b8362a0d..74c80d17bf 100644 --- a/coq/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.v +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,12 +15,12 @@ Implementation of the ALT_BN128 precompiled contracts. Require ethereum_types.numeric. Require ethereum.crypto.alt_bn128. -Require constantinople.vm. -Require constantinople.vm.gas. -Require constantinople.vm.memory. -Require constantinople.vm.exceptions. +Require ethereum.constantinople.vm. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.memory. +Require ethereum.constantinople.vm.exceptions. -Definition alt_bn128_add : M unit := +Definition alt_bn128_add (evm : Evm) : M unit := (* The ALT_BN128 addition precompiled contract. @@ -28,76 +29,96 @@ Definition alt_bn128_add : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* x1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x1_bytes - |) - |) in - let* y1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y1_bytes - |) - |) in + 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 *) - let* p := (* TODO expression *) in + do* M.assign "p" [[ + (* TODO expression *) in + ]] in (* TODO assignment *) + M.pure tt. - -Definition alt_bn128_mul : M unit := +Definition alt_bn128_mul (evm : Evm) : M unit := (* The ALT_BN128 multiplication precompiled contract. @@ -106,63 +127,77 @@ Definition alt_bn128_mul : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* n := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) (* TODO statement *) - let* p := p0.["mul_by"] (| - n - |) in + 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 : M unit := +Definition alt_bn128_pairing_check (evm : Evm) : M unit := (* The ALT_BN128 pairing check precompiled contract. @@ -171,17 +206,21 @@ Definition alt_bn128_pairing_check : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 (| + ethereum_types.numeric.Uint ~(| (* TODO expression *) |) - |) in + |) ]] in (* TODO statement *) - let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/constantinople/vm/precompiled_contracts/ecrecover.v index 87810b0f2f..774a2b92b7 100644 --- a/coq/ethereum/constantinople/vm/precompiled_contracts/ecrecover.v +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/ecrecover.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,11 +17,11 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require constantinople.vm. -Require constantinople.vm.gas. -Require constantinople.vm.memory. +Require ethereum.constantinople.vm. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.memory. -Definition ecrecover : M unit := +Definition ecrecover (evm : Evm) : M unit := (* Decrypts the address using elliptic curve DSA recovery mechanism and writes the address to output. @@ -30,64 +31,80 @@ Definition ecrecover : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* message_hash_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* message_hash := ethereum.crypto.hash.Hash32 (| - message_hash_bytes - |) in - let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + ethereum_types.numeric.U256 ~(| + 32 |) - |) - |) in - let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 + ]] 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 *) - let* address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/constantinople/vm/precompiled_contracts/identity.v index 484508fbe5..e5a3d27931 100644 --- a/coq/ethereum/constantinople/vm/precompiled_contracts/identity.v +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/identity.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,10 @@ Implementation of the `IDENTITY` precompiled contract. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require constantinople.vm. -Require constantinople.vm.gas. +Require ethereum.constantinople.vm. +Require ethereum.constantinople.vm.gas. -Definition identity : M unit := +Definition identity (evm : Evm) : M unit := (* Writes the message data to output. @@ -26,11 +27,15 @@ Definition identity : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/mapping.v b/coq/ethereum/constantinople/vm/precompiled_contracts/mapping.v index 0d67cdb857..b87db86b50 100644 --- a/coq/ethereum/constantinople/vm/precompiled_contracts/mapping.v +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/mapping.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Mapping of precompiled contracts their implementations. *) Require typing. -Require constantinople.fork_types. -Require constantinople.vm.precompiled_contracts.alt_bn128. -Require constantinople.vm.precompiled_contracts.ecrecover. -Require constantinople.vm.precompiled_contracts.identity. -Require constantinople.vm.precompiled_contracts.modexp. -Require constantinople.vm.precompiled_contracts.ripemd160. -Require constantinople.vm.precompiled_contracts.sha256. +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.v b/coq/ethereum/constantinople/vm/precompiled_contracts/modexp.v index 679c3bf4c6..71b48ffd58 100644 --- a/coq/ethereum/constantinople/vm/precompiled_contracts/modexp.v +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/modexp.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,100 +15,120 @@ Implementation of the `MODEXP` precompiled contract. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require constantinople.vm. -Require constantinople.vm.gas. -Require constantinople.vm.memory. +Require ethereum.constantinople.vm. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.memory. -Definition modexp : M unit := +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. *) - let* data := evm.["message"].["data"] in - let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) - |) in - let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 - let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* exp_start := (* TODO expression *) in - let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - min (| - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 |), - exp_length + ethereum_types.numeric.U256 ~(| + 32 + |) |) - |) - |) in - do* vm.gas.charge_gas (| + |) 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, - gas_cost (| - base_length, - modulus_length, - exp_length, - exp_head + 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 + |) ]] in (* TODO statement *) - let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - base_length - |) - |) in - let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - exp_length - |) - |) in - let* modulus_start := (* TODO expression *) in - let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - modulus_start, - modulus_length - |) - |) in + 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 : M unit := +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := (* Estimate the complexity of performing a modular exponentiation. @@ -126,18 +147,20 @@ Definition complexity : M unit := complexity : `Uint` Complexity of performing the operation. *) - let* max_length := max (| - ethereum_types.numeric.Uint (| - base_length - |), - ethereum_types.numeric.Uint (| - modulus_length - |) - |) in + 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 : M unit := +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := (* Calculate the number of iterations required to perform a modular exponentiation. @@ -160,9 +183,9 @@ Definition iterations : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition gas_cost : M unit := +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. @@ -188,15 +211,23 @@ Definition gas_cost : M unit := gas_cost : `Uint` Gas required for performing the operation. *) - let* multiplication_complexity := complexity (| - base_length, - modulus_length - |) in - let* iteration_count := iterations (| - exponent_length, - exponent_head - |) in - let* cost := (* TODO expression *) in - (* TODO statement *) + 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.v b/coq/ethereum/constantinople/vm/precompiled_contracts/ripemd160.v index bc5e73dd3c..fe2c66bbe6 100644 --- a/coq/ethereum/constantinople/vm/precompiled_contracts/ripemd160.v +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/ripemd160.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `RIPEMD160` precompiled contract. *) -Definition ripemd160 : M unit := +Definition ripemd160 (evm : Evm) : M unit := (* Writes the ripemd160 hash to output. @@ -22,21 +23,29 @@ Definition ripemd160 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 - let* hash_bytes := hashlib.["new"] (| - (* TODO expression *), - data - |).["digest"] (| - - |) in - let* padded_hash := left_pad_zero_bytes (| - hash_bytes, - (* TODO expression *) - |) in + |) ]] 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.v b/coq/ethereum/constantinople/vm/precompiled_contracts/sha256.v index da6972d411..3ba3ffe7aa 100644 --- a/coq/ethereum/constantinople/vm/precompiled_contracts/sha256.v +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/sha256.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `SHA256` precompiled contract. *) -Definition sha256 : M unit := +Definition sha256 (evm : Evm) : M unit := (* Writes the sha256 hash to output. @@ -22,11 +23,15 @@ Definition sha256 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/runtime.v b/coq/ethereum/constantinople/vm/runtime.v index 1888cf7bb2..d33b7f5f4c 100644 --- a/coq/ethereum/constantinople/vm/runtime.v +++ b/coq/ethereum/constantinople/vm/runtime.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Runtime Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Runtime related operations used while executing EVM code. Require typing. Require ethereum_types.numeric. -Require constantinople.vm.instructions. +Require ethereum.constantinople.vm.instructions. -Definition get_valid_jump_destinations : M unit := +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := (* Analyze the evm code to obtain the set of valid jump destinations. @@ -38,12 +39,16 @@ Definition get_valid_jump_destinations : M unit := valid_jump_destinations: `Set[Uint]` The set of valid jump destinations in the code. *) - let* valid_jump_destinations := set (| - - |) in - let* pc := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/constantinople/vm/stack.v index 56ea324c84..16737d1820 100644 --- a/coq/ethereum/constantinople/vm/stack.v +++ b/coq/ethereum/constantinople/vm/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Implementation of the stack operators for the EVM. Require typing. Require ethereum_types.numeric. -Require constantinople.vm.exceptions. +Require ethereum.constantinople.vm.exceptions. -Definition pop : M unit := +Definition pop (stack : (* TODO type *)) : M U256 := (* Pops the top item off of `stack`. @@ -33,9 +34,9 @@ Definition pop : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition push : M unit := +Definition push (stack : (* TODO type *)) (value : U256) : M unit := (* Pushes `value` onto `stack`. @@ -50,4 +51,4 @@ Definition push : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/crypto/__init__.v b/coq/ethereum/crypto/__init__.v index 3cf9aab6e1..79dc6dbc57 100644 --- a/coq/ethereum/crypto/__init__.v +++ b/coq/ethereum/crypto/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Cryptographic primitives used in Ethereum. *) diff --git a/coq/ethereum/crypto/alt_bn128.v b/coq/ethereum/crypto/alt_bn128.v index 3250649704..a2464bad7d 100644 --- a/coq/ethereum/crypto/alt_bn128.v +++ b/coq/ethereum/crypto/alt_bn128.v @@ -1,31 +1,33 @@ +(* Generated *) (* The alt_bn128 curve ^^^^^^^^^^^^^^^^^^^ *) +Require ethereum.crypto.__init__. -Definition bnf2_to_bnf12 : M unit := +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 : M unit := +Definition bnp_to_bnp12 (p : BNP) : M BNP12 := (* Lift a point from `BNP` to `BNP12`. *) (* TODO statement *) + M.pure tt. - -Definition twist : M unit := +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 : M unit := +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 @@ -36,42 +38,56 @@ Definition linefunc : M unit := matter. *) (* TODO statement *) + M.pure tt. - -Definition miller_loop : M unit := +Definition miller_loop (q : BNP12) (p : BNP12) : M BNF12 := (* The core of the pairing algorithm. *) (* TODO statement *) - let* r := q in - let* f := BNF12.["from_int"] (| - (* TODO expression *) - |) in + 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 *) - let* q1 := BNP12 (| - q.["x"].["frobenius"] (| - - |), - q.["y"].["frobenius"] (| - - |) - |) in - let* nq2 := BNP12 (| - q1.["x"].["frobenius"] (| - - |), - (* TODO expression *) - |) in - let* f := (* TODO expression *) in - let* r := (* TODO expression *) in - let* f := (* TODO expression *) in + 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 : M unit := +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.v b/coq/ethereum/crypto/blake2.v index 19be3410de..de14103999 100644 --- a/coq/ethereum/crypto/blake2.v +++ b/coq/ethereum/crypto/blake2.v @@ -1,10 +1,11 @@ +(* Generated *) (* The Blake2 Implementation ^^^^^^^^^^^^^^^^^^^^^^^^^^ *) -Definition spit_le_to_uint : M unit := +Definition spit_le_to_uint (data : bytes) (start : int) (num_words : int) : M (* TODO type *) := (* Extracts 8 byte words from a given data. @@ -17,7 +18,9 @@ Definition spit_le_to_uint : M unit := num_words: The number of words to be extracted *) - let* words := (* TODO expression *) in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/crypto/elliptic_curve.v b/coq/ethereum/crypto/elliptic_curve.v index 8d2abcc5dd..9a857622c7 100644 --- a/coq/ethereum/crypto/elliptic_curve.v +++ b/coq/ethereum/crypto/elliptic_curve.v @@ -1,3 +1,4 @@ +(* Generated *) (* Elliptic Curves ^^^^^^^^^^^^^^^ @@ -5,7 +6,7 @@ Elliptic Curves Require typing. -Definition secp256k1_recover : M unit := +Definition secp256k1_recover (r : U256) (s : U256) (v : U256) (msg_hash : Hash32) : M Bytes := (* Recovers the public key from a given signature. @@ -25,24 +26,34 @@ Definition secp256k1_recover : M unit := public_key : `ethereum.base_types.Bytes` Recovered public key. *) - let* r_bytes := r.["to_be_bytes32"] (| + do* M.assign "r_bytes" [[ + M.get_field ~(| r, "to_be_bytes32" |) ~(| - |) in - let* s_bytes := s.["to_be_bytes32"] (| + |) in + ]] in + do* M.assign "s_bytes" [[ + M.get_field ~(| s, "to_be_bytes32" |) ~(| - |) in - let* signature := bytearray (| - (* TODO expression *) - |) in + |) in + ]] in + do* M.assign "signature" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO assignment *) (* TODO assignment *) (* TODO assignment *) - let* public_key := coincurve.["PublicKey"].["from_signature_and_message"] (| - bytes (| - signature - |), - msg_hash - |) in - let* public_key := (* TODO expression *) in + 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.v b/coq/ethereum/crypto/finite_field.v index 4137029435..512b797838 100644 --- a/coq/ethereum/crypto/finite_field.v +++ b/coq/ethereum/crypto/finite_field.v @@ -1,3 +1,4 @@ +(* Generated *) (* Finite Fields ^^^^^^^^^^^^^ diff --git a/coq/ethereum/crypto/hash.v b/coq/ethereum/crypto/hash.v index 07b05e502d..3bf38bb95b 100644 --- a/coq/ethereum/crypto/hash.v +++ b/coq/ethereum/crypto/hash.v @@ -1,3 +1,4 @@ +(* Generated *) (* Cryptographic Hash Functions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,7 +16,7 @@ Cryptographic hashing functions. Require Crypto.Hash. Require ethereum_types.bytes. -Definition keccak256 : M unit := +Definition keccak256 (buffer : Bytes) : M Hash32 := (* Computes the keccak256 hash of the input `buffer`. @@ -29,13 +30,15 @@ Definition keccak256 : M unit := hash : `ethereum.base_types.Hash32` Output of the hash function. *) - let* k := Crypto.Hash.keccak.["new"] (| + do* M.assign "k" [[ + M.get_field ~(| Crypto.Hash.keccak, "new" |) ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition keccak512 : M unit := +Definition keccak512 (buffer : Bytes) : M Hash64 := (* Computes the keccak512 hash of the input `buffer`. @@ -49,8 +52,10 @@ Definition keccak512 : M unit := hash : `ethereum.base_types.Hash32` Output of the hash function. *) - let* k := Crypto.Hash.keccak.["new"] (| + do* M.assign "k" [[ + M.get_field ~(| Crypto.Hash.keccak, "new" |) ~(| - |) in + |) in + ]] in (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/crypto/kzg.v b/coq/ethereum/crypto/kzg.v index f238af8287..6c83228f1d 100644 --- a/coq/ethereum/crypto/kzg.v +++ b/coq/ethereum/crypto/kzg.v @@ -1,3 +1,4 @@ +(* Generated *) (* The KZG Implementation ^^^^^^^^^^^^^^^^^^^^^^ @@ -17,68 +18,72 @@ 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 : M unit := +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 : M unit := +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 : M unit := +Definition bytes_to_kzg_commitment (b : Bytes48) : M KZGCommitment := (* Convert untrusted bytes into a trusted and validated KZGCommitment. *) - do* validate_kzg_g1 (| + do* [[ M.get_local ~(| "validate_kzg_g1" |) ~(| b - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition bytes_to_bls_field : M unit := +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. *) - let* field_element := int.["from_bytes"] (| - b, - (* TODO expression *) - |) in + 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 : M unit := +Definition bytes_to_kzg_proof (b : Bytes48) : M KZGProof := (* Convert untrusted bytes into a trusted and validated KZGProof. *) - do* validate_kzg_g1 (| + do* [[ M.get_local ~(| "validate_kzg_g1" |) ~(| b - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition pairing_check : M unit := +Definition pairing_check (values : (* TODO type *)) : M bool := (* Check if the pairings are valid. *) (* TODO assignment *) - let* final_exponentiation := py_ecc.optimized_bls12_381.optimized_pairing.final_exponentiate (| - (* TODO expression *) - |) in + 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 : M unit := +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``. @@ -90,40 +95,44 @@ Definition verify_kzg_proof : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition verify_kzg_proof_impl : M unit := +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``. *) - let* 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 (| - KZG_SETUP_G2_MONOMIAL_1 + 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 *) |) |) - |), - py_ecc.optimized_bls12_381.multiply (| - py_ecc.optimized_bls12_381.optimized_curve.G2, - int (| - (* TODO expression *) - |) - |) - |) in - let* 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, - 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 + ]] in (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/dao_fork/__init__.v b/coq/ethereum/dao_fork/__init__.v index 914a333705..ad990a2598 100644 --- a/coq/ethereum/dao_fork/__init__.v +++ b/coq/ethereum/dao_fork/__init__.v @@ -1,3 +1,4 @@ +(* 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 diff --git a/coq/ethereum/dao_fork/blocks.v b/coq/ethereum/dao_fork/blocks.v index c5bce08268..7a2d0dd965 100644 --- a/coq/ethereum/dao_fork/blocks.v +++ b/coq/ethereum/dao_fork/blocks.v @@ -1,3 +1,4 @@ +(* 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 @@ -14,6 +15,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. -Require dao_fork.fork_types. -Require dao_fork.transactions. +Require ethereum.crypto.hash. +Require ethereum.dao_fork.fork_types. +Require ethereum.dao_fork.transactions. diff --git a/coq/ethereum/dao_fork/bloom.v b/coq/ethereum/dao_fork/bloom.v index eb4e32e729..4700caa011 100644 --- a/coq/ethereum/dao_fork/bloom.v +++ b/coq/ethereum/dao_fork/bloom.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Logs Bloom ^^^^^^^^^^^^^^^^^^^ @@ -19,10 +20,10 @@ eliminating blocks and receipts from their search. Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require dao_fork.blocks. -Require dao_fork.fork_types. +Require ethereum.dao_fork.blocks. +Require ethereum.dao_fork.fork_types. -Definition add_to_bloom : M unit := +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := (* Add a bloom entry to the bloom filter (`bloom`). @@ -37,13 +38,15 @@ Definition add_to_bloom : M unit := bloom_entry : An entry which is to be added to bloom filter. *) - let* hash := ethereum.crypto.hash.keccak256 (| - bloom_entry - |) in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition logs_bloom : M unit := +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := (* Obtain the logs bloom from a list of log entries. @@ -63,4 +66,4 @@ Definition logs_bloom : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/dao_fork/dao.v b/coq/ethereum/dao_fork/dao.v index bda8ac1af5..25bfae2721 100644 --- a/coq/ethereum/dao_fork/dao.v +++ b/coq/ethereum/dao_fork/dao.v @@ -1,3 +1,4 @@ +(* Generated *) (* Dao Fork ^^^^^^^^ @@ -15,10 +16,10 @@ collection of accounts (The Dao and all its children) to a recovery contract. The recovery contract was previously created using normal contract deployment. *) -Require dao_fork.state. -Require dao_fork.utils.hexadecimal. +Require ethereum.dao_fork.state. +Require ethereum.dao_fork.utils.hexadecimal. -Definition apply_dao : M unit := +Definition apply_dao (state : State) : M unit := (* Apply the dao fork to the state. @@ -28,4 +29,4 @@ Definition apply_dao : M unit := State before applying the DAO Fork. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/dao_fork/fork.v b/coq/ethereum/dao_fork/fork.v index c48075ab28..fe9204c2b4 100644 --- a/coq/ethereum/dao_fork/fork.v +++ b/coq/ethereum/dao_fork/fork.v @@ -1,3 +1,4 @@ +(* Generated *) (* .. _dao-fork: @@ -22,17 +23,19 @@ Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.ethash. Require ethereum.exceptions. -Require dao_fork.blocks. -Require dao_fork.bloom. -Require dao_fork.dao. -Require dao_fork.fork_types. -Require dao_fork.state. -Require dao_fork.transactions. -Require dao_fork.trie. -Require dao_fork.utils.message. -Require dao_fork.vm.interpreter. - -Definition apply_fork : M unit := +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. @@ -58,13 +61,13 @@ Definition apply_fork : M unit := new : `BlockChain` Upgraded block chain object for this hard fork. *) - do* dao.apply_dao (| - old.["state"] - |) in + do* [[ dao.apply_dao ~(| + M.get_field ~(| old, "state" |) + |) ]] in (* TODO statement *) + M.pure tt. - -Definition get_last_256_block_hashes : M unit := +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. @@ -84,22 +87,28 @@ Definition get_last_256_block_hashes : M unit := recent_block_hashes : `List[Hash32]` Hashes of the recent 256 blocks in order of increasing block number. *) - let* recent_blocks := (* TODO expression *) in - (* TODO statement *) - let* recent_block_hashes := (* TODO expression *) in - (* TODO statement *) - let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *).["header"] - |) - |) in - do* recent_block_hashes.["append"] (| - most_recent_block_hash - |) in - (* TODO statement *) - - -Definition state_transition : M unit := + 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. @@ -121,41 +130,45 @@ Definition state_transition : M unit := block : Block to apply to `chain`. *) - let* parent_header := (* TODO expression *).["header"] in - do* validate_header (| - block.["header"], - parent_header - |) in - do* validate_ommers (| - block.["ommers"], - block.["header"], + 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 - let* apply_body_output := apply_body (| - chain.["state"], - get_last_256_block_hashes (| - chain - |), - block.["header"].["coinbase"], - block.["header"].["number"], - block.["header"].["gas_limit"], - block.["header"].["timestamp"], - block.["header"].["difficulty"], - block.["transactions"], - block.["ommers"] - |) in + |) ]] 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* chain.["blocks"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| block - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition validate_header : M unit := +Definition validate_header (header : Header) (parent_header : Header) : M unit := (* Verifies a block header. @@ -177,26 +190,30 @@ Definition validate_header : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* block_difficulty := calculate_block_difficulty (| - header.["number"], - header.["timestamp"], - parent_header.["timestamp"], - parent_header.["difficulty"] - |) in + 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 *) - let* block_parent_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - parent_header - |) - |) in + 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* validate_proof_of_work (| + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| header - |) in + |) ]] in + M.pure tt. - -Definition generate_header_hash_for_pow : M unit := +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. @@ -219,11 +236,13 @@ Definition generate_header_hash_for_pow : M unit := hash : `Hash32` The PoW valid rlp hash of the passed in header. *) - let* header_data_without_pow_artefacts := (* TODO expression *) in + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition validate_proof_of_work : M unit := +Definition validate_proof_of_work (header : Header) : M unit := (* Validates the Proof of Work constraints. @@ -238,19 +257,25 @@ Definition validate_proof_of_work : M unit := header : Header of interest. *) - let* header_hash := generate_header_hash_for_pow (| - header - |) in - let* cache := ethereum.ethash.generate_cache (| - header.["number"] - |) in + 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 *) - let* limit := (* TODO expression *) in + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition check_transaction : M unit := +Definition check_transaction (tx : Transaction) (gas_available : Uint) : M Address := (* Check if the transaction is includable in the block. @@ -272,13 +297,15 @@ Definition check_transaction : M unit := If the transaction is not includable. *) (* TODO statement *) - let* sender_address := recover_sender (| - tx - |) in + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + tx + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition make_receipt : M unit := +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. @@ -299,13 +326,15 @@ Definition make_receipt : M unit := receipt : The receipt for the transaction. *) - let* receipt := blocks.Receipt (| + do* M.assign "receipt" [[ + blocks.Receipt ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition apply_body : M unit := +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. @@ -344,25 +373,31 @@ Definition apply_body : M unit := apply_body_output : `ApplyBodyOutput` Output of applying the block body to the state. *) - let* gas_available := block_gas_limit in + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - do* pay_rewards (| + do* [[ M.get_local ~(| "pay_rewards" |) ~(| state, block_number, coinbase, ommers - |) in - let* block_gas_used := (* TODO expression *) in - let* block_logs_bloom := bloom.logs_bloom (| - block_logs - |) in - (* TODO statement *) - - -Definition validate_ommers : M unit := + |) ]] 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. @@ -384,23 +419,31 @@ Definition validate_ommers : M unit := chain : History and current state. *) - let* block_hash := rlp.["rlp_hash"] (| - block_header - |) in + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* ommers_hashes := (* TODO expression *) in + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* recent_canonical_blocks := (* TODO expression *) in - let* recent_canonical_block_hashes := (* TODO expression *) in + 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 : M unit := +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. @@ -426,21 +469,25 @@ Definition pay_rewards : M unit := ommers : List of ommers mentioned in the current block. *) - let* ommer_count := ethereum_types.numeric.U256 (| - len (| - ommers - |) - |) in - let* miner_reward := (* TODO expression *) in - do* state.create_ether (| + 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, - miner_reward - |) in + M.get_local ~(| "miner_reward" |) + |) ]] in (* TODO statement *) + M.pure tt. - -Definition process_transaction : M unit := +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := (* Execute a transaction against the provided environment. @@ -468,67 +515,95 @@ Definition process_transaction : M unit := Logs generated during execution. *) (* TODO statement *) - let* sender := env.["origin"] in - let* sender_account := state.get_account (| - env.["state"], - sender - |) in - let* gas_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* gas := (* TODO expression *) in - do* state.increment_nonce (| - env.["state"], - sender - |) in - let* sender_balance_after_gas_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - ethereum_types.numeric.U256 (| - sender_balance_after_gas_fee + 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 - let* message := utils.message.prepare_message (| - sender, - tx.["to"], - tx.["value"], - tx.["data"], - gas, - env - |) in - let* output := vm.interpreter.process_message_call (| - message, - env - |) in - let* gas_used := (* TODO expression *) in - let* gas_refund := min (| - (* TODO expression *), - ethereum_types.numeric.Uint (| - output.["refund_counter"] - |) - |) in - let* gas_refund_amount := (* TODO expression *) in - let* transaction_fee := (* TODO expression *) in - let* total_gas_used := (* TODO expression *) in - let* sender_balance_after_refund := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - sender_balance_after_refund - |) in - let* coinbase_balance_after_mining_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - env.["coinbase"], - coinbase_balance_after_mining_fee - |) in - (* TODO statement *) - (* TODO statement *) - - -Definition validate_transaction : M unit := + |) ]] 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. @@ -556,9 +631,9 @@ Definition validate_transaction : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition calculate_intrinsic_cost : M unit := +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := (* Calculates the gas that is charged before execution is started. @@ -581,13 +656,15 @@ Definition calculate_intrinsic_cost : M unit := verified : `ethereum.base_types.Uint` The intrinsic cost of the transaction. *) - let* data_cost := (* TODO expression *) in + do* M.assign "data_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition recover_sender : M unit := +Definition recover_sender (tx : Transaction) : M Address := (* Extracts the sender address from a transaction. @@ -611,18 +688,20 @@ Definition recover_sender : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* public_key := ethereum.crypto.elliptic_curve.secp256k1_recover (| - r, - s, - (* TODO expression *), - signing_hash (| - tx - |) - |) in + 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 : M unit := +Definition signing_hash (tx : Transaction) : M Hash32 := (* Compute the hash of a transaction used in the signature. @@ -641,9 +720,9 @@ Definition signing_hash : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition compute_header_hash : M unit := +Definition compute_header_hash (header : Header) : M Hash32 := (* Computes the hash of a block header. @@ -676,9 +755,9 @@ Definition compute_header_hash : M unit := Hash of the header. *) (* TODO statement *) + M.pure tt. - -Definition check_gas_limit : M unit := +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := (* Validates the gas limit for a block. @@ -706,14 +785,16 @@ Definition check_gas_limit : M unit := check : `bool` True if gas limit constraints are satisfied, False otherwise. *) - let* max_adjustment_delta := (* TODO expression *) in + 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 : M unit := +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. @@ -750,9 +831,15 @@ Definition calculate_block_difficulty : M unit := difficulty : `ethereum.base_types.Uint` Computed difficulty for a block. *) - let* offset := (* TODO expression *) in - let* difficulty := (* TODO expression *) in - let* num_bomb_periods := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - + 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.v b/coq/ethereum/dao_fork/fork_types.v index 14de99d5e5..d84cffdf45 100644 --- a/coq/ethereum/dao_fork/fork_types.v +++ b/coq/ethereum/dao_fork/fork_types.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Types ^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. +Require ethereum.__init__. +Require ethereum.crypto.hash. -Definition encode_account : M unit := +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := (* Encode `Account` dataclass. @@ -26,4 +28,4 @@ Definition encode_account : M unit := encoded without providing a storage root. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/dao_fork/state.v b/coq/ethereum/dao_fork/state.v index fd32ea6e73..917493dc44 100644 --- a/coq/ethereum/dao_fork/state.v +++ b/coq/ethereum/dao_fork/state.v @@ -1,3 +1,4 @@ +(* Generated *) (* State ^^^^^ @@ -22,10 +23,10 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require dao_fork.fork_types. -Require dao_fork.trie. +Require ethereum.dao_fork.fork_types. +Require ethereum.dao_fork.trie. -Definition close_state : M unit := +Definition close_state (state : State) : M unit := (* Free resources held by the state. Used by optimized implementations to release file descriptors. @@ -33,9 +34,9 @@ Definition close_state : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition begin_transaction : M unit := +Definition begin_transaction (state : State) : M unit := (* Start a state transaction. @@ -47,12 +48,12 @@ Definition begin_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition commit_transaction : M unit := +Definition commit_transaction (state : State) : M unit := (* Commit a state transaction. @@ -61,12 +62,12 @@ Definition commit_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["pop"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| - |) in + |) ]] in + M.pure tt. - -Definition rollback_transaction : M unit := +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. @@ -77,9 +78,9 @@ Definition rollback_transaction : M unit := The state. *) (* TODO assignment *) + M.pure tt. - -Definition get_account : M unit := +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. @@ -99,14 +100,16 @@ Definition get_account : M unit := account : `Account` Account at address. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition get_account_optional : M unit := +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. @@ -123,14 +126,16 @@ Definition get_account_optional : M unit := account : `Account` Account at address. *) - let* account := trie.trie_get (| - state.["_main_trie"], - address - |) in + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition set_account : M unit := +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()`). @@ -144,14 +149,14 @@ Definition set_account : M unit := account : `Account` Account to set at address. *) - do* trie.trie_set (| - state.["_main_trie"], + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), address, account - |) in - + |) ]] in + M.pure tt. -Definition destroy_account : M unit := +Definition destroy_account (state : State) (address : Address) : M unit := (* Completely remove the account at `address` and all of its storage. @@ -166,18 +171,18 @@ Definition destroy_account : M unit := address : `Address` Address of account to destroy. *) - do* destroy_storage (| + do* [[ M.get_local ~(| "destroy_storage" |) ~(| state, address - |) in - do* set_account (| + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - (* TODO expression *) - |) in - + tt + |) ]] in + M.pure tt. -Definition destroy_storage : M unit := +Definition destroy_storage (state : State) (address : Address) : M unit := (* Completely remove the storage at `address`. @@ -189,9 +194,9 @@ Definition destroy_storage : M unit := Address of account whose storage is to be deleted. *) (* TODO statement *) + M.pure tt. - -Definition get_storage : M unit := +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. @@ -210,19 +215,23 @@ Definition get_storage : M unit := value : `U256` Value at the key. *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition set_storage : M unit := +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. @@ -239,19 +248,21 @@ Definition set_storage : M unit := Value to set at the key. *) (* TODO statement *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - do* trie.trie_set (| - trie, + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), key, value - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition storage_root : M unit := +Definition storage_root (state : State) (address : Address) : M Root := (* Calculate the storage root of an account. @@ -269,9 +280,9 @@ Definition storage_root : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition state_root : M unit := +Definition state_root (state : State) : M Root := (* Calculate the state root. @@ -288,9 +299,9 @@ Definition state_root : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition account_exists : M unit := +Definition account_exists (state : State) (address : Address) : M bool := (* Checks if an account exists in the state trie @@ -307,9 +318,9 @@ Definition account_exists : M unit := True if account exists in the state trie, False otherwise *) (* TODO statement *) + M.pure tt. - -Definition account_has_code_or_nonce : M unit := +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := (* Checks if an account has non zero nonce or non empty code @@ -326,49 +337,51 @@ Definition account_has_code_or_nonce : M unit := True if if an account has non zero nonce or non empty code, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition modify_state : M unit := +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := (* Modify an `Account` in the `State`. *) - do* set_account (| + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - ethereum_types.frozen.modify (| - get_account (| + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| state, address |), f |) - |) in + |) ]] in + M.pure tt. - -Definition move_ether : M unit := +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := (* Move funds between accounts. *) (* TODO statement *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, sender_address, - reduce_sender_balance - |) in - do* modify_state (| + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| state, recipient_address, - increase_recipient_balance - |) in - + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. -Definition set_account_balance : M unit := +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := (* Sets the balance of an account. @@ -384,14 +397,14 @@ Definition set_account_balance : M unit := The amount that needs to set in balance. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - set_balance - |) in + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. - -Definition touch_account : M unit := +Definition touch_account (state : State) (address : Address) : M unit := (* Initializes an account to state. @@ -404,9 +417,9 @@ Definition touch_account : M unit := The address of the account that need to initialised. *) (* TODO statement *) + M.pure tt. - -Definition increment_nonce : M unit := +Definition increment_nonce (state : State) (address : Address) : M unit := (* Increments the nonce of an account. @@ -419,14 +432,14 @@ Definition increment_nonce : M unit := Address of the account whose nonce needs to be incremented. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_nonce - |) in + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. - -Definition set_code : M unit := +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := (* Sets Account code. @@ -442,14 +455,14 @@ Definition set_code : M unit := The bytecode that needs to be set. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - write_code - |) in - + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. -Definition create_ether : M unit := +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := (* Add newly created ether to an account. @@ -463,9 +476,9 @@ Definition create_ether : M unit := The amount of ether to be added to the account of interest. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_balance - |) in - + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. diff --git a/coq/ethereum/dao_fork/transactions.v b/coq/ethereum/dao_fork/transactions.v index 499d5305a6..d113f3f58f 100644 --- a/coq/ethereum/dao_fork/transactions.v +++ b/coq/ethereum/dao_fork/transactions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, @@ -9,4 +10,4 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require dao_fork.fork_types. +Require ethereum.dao_fork.fork_types. diff --git a/coq/ethereum/dao_fork/trie.v b/coq/ethereum/dao_fork/trie.v index 548de91e1c..6b8953f256 100644 --- a/coq/ethereum/dao_fork/trie.v +++ b/coq/ethereum/dao_fork/trie.v @@ -1,3 +1,4 @@ +(* Generated *) (* State Trie ^^^^^^^^^^ @@ -14,7 +15,7 @@ The state trie is the structure responsible for storing *) -Definition encode_internal_node : M unit := +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 @@ -35,22 +36,24 @@ Definition encode_internal_node : M unit := *) (* TODO statement *) (* TODO statement *) - let* encoded := rlp.["encode"] (| - unencoded - |) in + 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 : M unit := +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 : M unit := +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. @@ -66,9 +69,9 @@ Definition copy_trie : M unit := A copy of the trie. *) (* TODO statement *) + M.pure tt. - -Definition trie_set : M unit := +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := (* Stores an item in a Merkle Trie. @@ -85,9 +88,9 @@ Definition trie_set : M unit := Node to insert at `key`. *) (* TODO statement *) + M.pure tt. - -Definition trie_get : M unit := +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := (* Gets an item from the Merkle Trie. @@ -106,17 +109,17 @@ Definition trie_get : M unit := Node at `key` in the trie. *) (* TODO statement *) + M.pure tt. - -Definition common_prefix_length : M unit := +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 : M unit := +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := (* Compresses nibble-list into a standard byte array with a flag. @@ -150,14 +153,16 @@ Definition nibble_list_to_compact : M unit := compressed : `bytearray` Compact byte array. *) - let* compact := bytearray (| + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition bytes_to_nibble_list : M unit := +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := (* Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). @@ -171,14 +176,16 @@ Definition bytes_to_nibble_list : M unit := nibble_list : `Bytes` The `Bytes` in nibble-list format. *) - let* nibble_list := bytearray (| - (* TODO expression *) - |) in + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _prepare_trie : M unit := +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. @@ -199,9 +206,9 @@ Definition _prepare_trie : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition root : M unit := +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := (* Computes the root of a modified merkle patricia trie (MPT). @@ -219,22 +226,26 @@ Definition root : M unit := root : `.fork_types.Root` MPT root of the underlying key-value pairs. *) - let* obj := _prepare_trie (| - trie, - get_storage_root - |) in - let* root_node := encode_internal_node (| - patricialize (| - obj, - Uint (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) + M.pure tt. - -Definition patricialize : M unit := +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := (* Structural composition function. @@ -254,21 +265,29 @@ Definition patricialize : M unit := Root node of `obj`. *) (* TODO statement *) - let* arbitrary_key := next (| - iter (| - obj - |) - |) in + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in (* TODO statement *) - let* substring := (* TODO expression *) in - let* prefix_length := len (| - substring - |) in + 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 *) - let* value := (* TODO expression *) in + do* M.assign "value" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/dao_fork/utils/__init__.v b/coq/ethereum/dao_fork/utils/__init__.v index beff4482b1..7f30fe939b 100644 --- a/coq/ethereum/dao_fork/utils/__init__.v +++ b/coq/ethereum/dao_fork/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions unique to this particular fork. *) diff --git a/coq/ethereum/dao_fork/utils/address.v b/coq/ethereum/dao_fork/utils/address.v index 1a0612f347..ae6dafeeff 100644 --- a/coq/ethereum/dao_fork/utils/address.v +++ b/coq/ethereum/dao_fork/utils/address.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require dao_fork.fork_types. +Require ethereum.__init__. +Require ethereum.dao_fork.fork_types. -Definition to_address : M unit := +Definition to_address (data : (* TODO type *)) : M Address := (* Convert a Uint or U256 value to a valid address (20 bytes). @@ -33,9 +35,9 @@ Definition to_address : M unit := The obtained address. *) (* TODO statement *) + M.pure tt. - -Definition compute_contract_address : M unit := +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := (* Computes address of the new account that needs to be created. @@ -52,15 +54,21 @@ Definition compute_contract_address : M unit := address: `ethereum.dao_fork.fork_types.Address` The computed address of the new account. *) - let* computed_address := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *) - |) - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/dao_fork/utils/hexadecimal.v index 3d24a9bec3..e4b373176a 100644 --- a/coq/ethereum/dao_fork/utils/hexadecimal.v +++ b/coq/ethereum/dao_fork/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ types. *) Require ethereum.utils.hexadecimal. -Require dao_fork.fork_types. +Require ethereum.dao_fork.fork_types. -Definition hex_to_root : M unit := +Definition hex_to_root (hex_string : str) : M Root := (* Convert hex string to trie root. @@ -31,9 +32,9 @@ Definition hex_to_root : M unit := Trie root obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bloom : M unit := +Definition hex_to_bloom (hex_string : str) : M Bloom := (* Convert hex string to bloom. @@ -48,9 +49,9 @@ Definition hex_to_bloom : M unit := Bloom obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_address : M unit := +Definition hex_to_address (hex_string : str) : M Address := (* Convert hex string to Address (20 bytes). @@ -65,4 +66,4 @@ Definition hex_to_address : M unit := The address obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/dao_fork/utils/message.v b/coq/ethereum/dao_fork/utils/message.v index aab7d018ff..1cc3cf4313 100644 --- a/coq/ethereum/dao_fork/utils/message.v +++ b/coq/ethereum/dao_fork/utils/message.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For The Message Data-structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,12 +16,12 @@ Message specific functions used in this Dao Fork version of specification. Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require dao_fork.fork_types. -Require dao_fork.state. -Require dao_fork.vm. -Require dao_fork.utils.address. +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 : M unit := +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. @@ -52,4 +53,4 @@ Definition prepare_message : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/__init__.v b/coq/ethereum/dao_fork/vm/__init__.v index 52d657c646..97024ca4f8 100644 --- a/coq/ethereum/dao_fork/vm/__init__.v +++ b/coq/ethereum/dao_fork/vm/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,11 +19,11 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require dao_fork.blocks. -Require dao_fork.fork_types. -Require dao_fork.state. +Require ethereum.dao_fork.blocks. +Require ethereum.dao_fork.fork_types. +Require ethereum.dao_fork.state. -Definition incorporate_child_on_success : M unit := +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of a successful `child_evm` into the parent `evm`. @@ -33,15 +34,21 @@ Definition incorporate_child_on_success : M unit := child_evm : The child evm to incorporate. *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - do* evm.["accounts_to_delete"].["update"] (| - child_evm.["accounts_to_delete"] - |) in + 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 : M unit := +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. @@ -52,5 +59,7 @@ Definition incorporate_child_on_error : M unit := child_evm : The child evm to incorporate. *) - (* 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/dao_fork/vm/exceptions.v b/coq/ethereum/dao_fork/vm/exceptions.v index 1784494410..47e26555d5 100644 --- a/coq/ethereum/dao_fork/vm/exceptions.v +++ b/coq/ethereum/dao_fork/vm/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Exceptions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/dao_fork/vm/gas.v b/coq/ethereum/dao_fork/vm/gas.v index 0bad5a417e..d5b4511bf7 100644 --- a/coq/ethereum/dao_fork/vm/gas.v +++ b/coq/ethereum/dao_fork/vm/gas.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Gas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,11 +18,12 @@ Require typing. Require ethereum_types.numeric. Require ethereum.trace. Require ethereum.utils.numeric. -Require dao_fork.fork_types. -Require dao_fork.state. -Require dao_fork.vm.exceptions. +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 : M unit := +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := (* Subtracts `amount` from `evm.gas_left`. @@ -33,18 +35,18 @@ Definition charge_gas : M unit := The amount of gas the current operation requires. *) - do* ethereum.trace.evm_trace (| + do* [[ ethereum.trace.evm_trace ~(| evm, - ethereum.trace.GasAndRefund (| - int (| + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| amount |) |) - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_memory_gas_cost : M unit := +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, @@ -60,14 +62,22 @@ Definition calculate_memory_gas_cost : M unit := total_gas_cost : `ethereum.base_types.Uint` The gas cost for storing data in memory. *) - let* size_in_words := (* TODO expression *) in - let* linear_cost := (* TODO expression *) in - let* quadratic_cost := (* TODO expression *) in - let* total_gas_cost := (* TODO expression *) in + 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 : M unit := +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := (* Calculates the gas amount to extend memory @@ -83,22 +93,28 @@ Definition calculate_gas_extend_memory : M unit := ------- extend_memory: `ExtendMemory` *) - let* size_to_extend := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* to_be_paid := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* current_size := ethereum_types.numeric.Uint (| - len (| - memory - |) - |) in + 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 : M unit := +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`. @@ -117,9 +133,17 @@ Definition calculate_message_call_gas : M unit := ------- message_call_gas: `MessageCallGas` *) - let* create_gas_cost := (* TODO expression *) in - let* transfer_gas_cost := (* TODO expression *) in - let* cost := (* TODO expression *) in - let* stipend := (* TODO expression *) in + 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__.v b/coq/ethereum/dao_fork/vm/instructions/__init__.v index b36b1ebfef..cbd7e7e63a 100644 --- a/coq/ethereum/dao_fork/vm/instructions/__init__.v +++ b/coq/ethereum/dao_fork/vm/instructions/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* EVM Instruction Encoding (Opcodes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/dao_fork/vm/instructions/arithmetic.v b/coq/ethereum/dao_fork/vm/instructions/arithmetic.v index 4a435c46f1..d825516ace 100644 --- a/coq/ethereum/dao_fork/vm/instructions/arithmetic.v +++ b/coq/ethereum/dao_fork/vm/instructions/arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,11 @@ Implementations of the EVM Arithmetic instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require dao_fork.vm.gas. -Require dao_fork.vm.stack. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.stack. -Definition add : M unit := +Definition add (evm : Evm) : M unit := (* Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -28,27 +30,37 @@ Definition add : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_add"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sub (evm : Evm) : M unit := (* Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -59,27 +71,37 @@ Definition sub : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_sub"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mul (evm : Evm) : M unit := (* Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -90,27 +112,37 @@ Definition mul : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_mul"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition div (evm : Evm) : M unit := (* Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -121,25 +153,33 @@ Definition div : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |) in - let* divisor := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - quotient - |) 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 : M unit := +Definition sdiv (evm : Evm) : M unit := (* Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -150,31 +190,39 @@ Definition sdiv : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* divisor := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - quotient + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mod : M unit := +Definition mod (evm : Evm) : M unit := (* Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -185,25 +233,33 @@ Definition mod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - remainder - |) in + |) ]] 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 : M unit := +Definition smod (evm : Evm) : M unit := (* Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -214,31 +270,39 @@ Definition smod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* y := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - remainder + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition addmod : M unit := +Definition addmod (evm : Evm) : M unit := (* Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -249,34 +313,44 @@ Definition addmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +Definition mulmod (evm : Evm) : M unit := (* Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -287,34 +361,44 @@ Definition mulmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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 : M unit := +Definition exp (evm : Evm) : M unit := (* Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -325,39 +409,53 @@ Definition exp : M unit := The current EVM frame. *) - let* base := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent_bits := exponent.["bit_length"] (| - - |) in - let* exponent_bytes := (* TODO expression *) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - pow (| - base, - exponent, - (* 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 - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition signextend : M unit := +Definition signextend (evm : Evm) : M unit := (* Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -368,20 +466,28 @@ Definition signextend : M unit := The current EVM frame. *) - let* byte_num := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/dao_fork/vm/instructions/bitwise.v index 682682eb38..0397f10c19 100644 --- a/coq/ethereum/dao_fork/vm/instructions/bitwise.v +++ b/coq/ethereum/dao_fork/vm/instructions/bitwise.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Bitwise Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM bitwise instructions. *) Require ethereum_types.numeric. -Require dao_fork.vm.gas. -Require dao_fork.vm.stack. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.stack. -Definition bitwise_and : M unit := +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. @@ -27,24 +29,32 @@ Definition bitwise_and : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_or : M unit := + |) ]] 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. @@ -55,24 +65,32 @@ Definition bitwise_or : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_xor : M unit := + |) ]] 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. @@ -83,24 +101,32 @@ Definition bitwise_xor : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_not : M unit := + |) ]] 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. @@ -111,21 +137,27 @@ Definition bitwise_not : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition get_byte : M unit := + |) ]] 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 @@ -137,20 +169,28 @@ Definition get_byte : M unit := The current EVM frame. *) - let* byte_index := stack.pop (| - evm.["stack"] - |) in - let* word := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/dao_fork/vm/instructions/block.v index 06298223b7..a3799da32a 100644 --- a/coq/ethereum/dao_fork/vm/instructions/block.v +++ b/coq/ethereum/dao_fork/vm/instructions/block.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Block Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM block instructions. *) Require ethereum_types.numeric. -Require dao_fork.vm.gas. -Require dao_fork.vm.stack. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.stack. -Definition block_hash : M unit := +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. @@ -27,27 +29,35 @@ Definition block_hash : M unit := The current EVM frame. *) - let* block_number := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* max_block_number := (* TODO expression *) in + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition coinbase : M unit := +Definition coinbase (evm : Evm) : M unit := (* Push the current block's beneficiary address (address of the block miner) onto the stack. @@ -62,20 +72,24 @@ Definition coinbase : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["coinbase"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition timestamp : M unit := +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. @@ -90,18 +104,22 @@ Definition timestamp : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["env"].["time"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition number (evm : Evm) : M unit := (* Push the current block's number onto the stack. @@ -115,20 +133,24 @@ Definition number : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["number"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition difficulty : M unit := +Definition difficulty (evm : Evm) : M unit := (* Push the current block's difficulty onto the stack. @@ -142,20 +164,24 @@ Definition difficulty : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["difficulty"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_limit : M unit := +Definition gas_limit (evm : Evm) : M unit := (* Push the current block's gas limit onto the stack. @@ -169,15 +195,19 @@ Definition gas_limit : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_limit"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/dao_fork/vm/instructions/comparison.v index 1cf3a9aebd..87b493c750 100644 --- a/coq/ethereum/dao_fork/vm/instructions/comparison.v +++ b/coq/ethereum/dao_fork/vm/instructions/comparison.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Comparison Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM Comparison instructions. *) Require ethereum_types.numeric. -Require dao_fork.vm.gas. -Require dao_fork.vm.stack. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.stack. -Definition less_than : M unit := +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. @@ -27,27 +29,37 @@ Definition less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_less_than : M unit := + |) ]] 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. @@ -57,31 +69,41 @@ Definition signed_less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition greater_than : M unit := + |) ]] 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. @@ -92,27 +114,37 @@ Definition greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_greater_than : M unit := + |) ]] 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. @@ -122,31 +154,41 @@ Definition signed_greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition equal : M unit := + |) ]] 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. @@ -157,27 +199,37 @@ Definition equal : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition is_zero : M unit := + |) ]] 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. @@ -188,19 +240,27 @@ Definition is_zero : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/dao_fork/vm/instructions/control_flow.v index 3cb1d463cf..e71d79a9db 100644 --- a/coq/ethereum/dao_fork/vm/instructions/control_flow.v +++ b/coq/ethereum/dao_fork/vm/instructions/control_flow.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Control Flow Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM control flow instructions. *) Require ethereum_types.numeric. -Require dao_fork.vm.gas. -Require dao_fork.vm.exceptions. -Require dao_fork.vm.stack. +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 : M unit := +Definition stop (evm : Evm) : M unit := (* Stop further execution of EVM code. @@ -29,10 +31,14 @@ Definition stop : M unit := (* TODO statement *) (* TODO statement *) (* TODO assignment *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jump : M unit := +Definition jump (evm : Evm) : M unit := (* Alter the program counter to the location specified by the top of the stack. @@ -43,20 +49,22 @@ Definition jump : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition jumpi : M unit := +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 @@ -68,23 +76,27 @@ Definition jumpi : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* conditional_value := stack.pop (| - evm.["stack"] - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition pc : M unit := +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. @@ -96,20 +108,24 @@ Definition pc : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["pc"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_left : M unit := +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. @@ -121,20 +137,24 @@ Definition gas_left : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["gas_left"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jumpdest : M unit := +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 @@ -147,10 +167,14 @@ Definition jumpdest : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_JUMPDEST - |) in - (* TODO statement *) + |) ]] 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.v b/coq/ethereum/dao_fork/vm/instructions/environment.v index 0e0a714f5b..16113bad15 100644 --- a/coq/ethereum/dao_fork/vm/instructions/environment.v +++ b/coq/ethereum/dao_fork/vm/instructions/environment.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,13 +15,14 @@ Implementations of the EVM environment related instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require dao_fork.state. -Require dao_fork.utils.address. -Require dao_fork.vm.memory. -Require dao_fork.vm.gas. -Require dao_fork.vm.stack. - -Definition address : M unit := +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. @@ -31,20 +33,24 @@ Definition address : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["current_target"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition balance : M unit := +Definition balance (evm : Evm) : M unit := (* Pushes the balance of the given account onto the stack. @@ -54,27 +60,35 @@ Definition balance : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* balance := state.get_account (| - evm.["env"].["state"], - address - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +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. @@ -86,20 +100,24 @@ Definition origin : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["origin"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition caller : M unit := +Definition caller (evm : Evm) : M unit := (* Pushes the address of the caller onto the stack. @@ -110,20 +128,24 @@ Definition caller : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["caller"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition callvalue : M unit := +Definition callvalue (evm : Evm) : M unit := (* Push the value (in wei) sent with the call onto the stack. @@ -134,18 +156,22 @@ Definition callvalue : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["message"].["value"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition calldataload (evm : Evm) : M unit := (* Push a word (32 bytes) of the input data belonging to the current environment onto the stack. @@ -156,30 +182,38 @@ Definition calldataload : M unit := The current EVM frame. *) - let* start_index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - start_index, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] 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* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - value + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 |) - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition calldatasize : M unit := +Definition calldatasize (evm : Evm) : M unit := (* Push the size of input data in current environment onto the stack. @@ -190,22 +224,26 @@ Definition calldatasize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["message"].["data"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition calldatacopy : M unit := +Definition calldatacopy (evm : Evm) : M unit := (* Copy a portion of the input data in current environment to memory. @@ -218,40 +256,60 @@ Definition calldatacopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* data_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - data_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition codesize (evm : Evm) : M unit := (* Push the size of code running in current environment onto the stack. @@ -262,22 +320,26 @@ Definition codesize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["code"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition codecopy : M unit := +Definition codecopy (evm : Evm) : M unit := (* Copy a portion of the code in current environment to memory. @@ -290,40 +352,60 @@ Definition codecopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["code"], - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition gasprice (evm : Evm) : M unit := (* Push the gas price used in current environment onto the stack. @@ -334,20 +416,24 @@ Definition gasprice : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_price"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition extcodesize : M unit := +Definition extcodesize (evm : Evm) : M unit := (* Push the code size of a given account onto the stack. @@ -357,31 +443,39 @@ Definition extcodesize : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* codesize := ethereum_types.numeric.U256 (| - len (| - state.get_account (| - evm.["env"].["state"], - address - |).["code"] + |) ]] 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 - do* stack.push (| - evm.["stack"], - codesize - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition extcodecopy : M unit := +Definition extcodecopy (evm : Evm) : M unit := (* Copy a portion of an account's code to memory. @@ -391,44 +485,68 @@ Definition extcodecopy : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* code := state.get_account (| - evm.["env"].["state"], - address - |).["code"] in - let* value := vm.memory.buffer_read (| - code, - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/dao_fork/vm/instructions/keccak.v index 21a120efc3..c8d1583221 100644 --- a/coq/ethereum/dao_fork/vm/instructions/keccak.v +++ b/coq/ethereum/dao_fork/vm/instructions/keccak.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Keccak Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM keccak instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require dao_fork.vm.gas. -Require dao_fork.vm.memory. -Require dao_fork.vm.stack. +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 : M unit := +Definition keccak (evm : Evm) : M unit := (* Pushes to the stack the Keccak-256 hash of a region of memory. @@ -32,36 +34,56 @@ Definition keccak : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* word_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in - let* hash := ethereum.crypto.hash.keccak256 (| - data - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/dao_fork/vm/instructions/log.v index 8e37508fa5..916178e9a1 100644 --- a/coq/ethereum/dao_fork/vm/instructions/log.v +++ b/coq/ethereum/dao_fork/vm/instructions/log.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Logging Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,12 +15,13 @@ Implementations of the EVM logging instructions. Require functools. Require ethereum_types.numeric. -Require dao_fork.blocks. -Require dao_fork.vm.gas. -Require dao_fork.vm.memory. -Require dao_fork.vm.stack. +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 : M unit := +Definition log_n (evm : Evm) (num_topics : U256) : M unit := (* Appends a log entry, having `num_topics` topics, to the evm logs. @@ -34,26 +36,42 @@ Definition log_n : M unit := The number of topics to be included in the log entry. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* topics := (* TODO expression *) in + 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 *) - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - let* log_entry := blocks.Log (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "log_entry" [[ + blocks.Log ~(| - |) in + |) in + ]] in (* TODO assignment *) - (* 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/memory.v b/coq/ethereum/dao_fork/vm/instructions/memory.v index 20cbc79690..16d2dcf365 100644 --- a/coq/ethereum/dao_fork/vm/instructions/memory.v +++ b/coq/ethereum/dao_fork/vm/instructions/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM Memory instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require dao_fork.vm.gas. -Require dao_fork.vm.memory. -Require dao_fork.vm.stack. +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 : M unit := +Definition mstore (evm : Evm) : M unit := (* Stores a word to memory. This also expands the memory, if the memory is @@ -30,32 +32,44 @@ Definition mstore : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* memory.memory_write (| - evm.["memory"], - start_position, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mstore8 (evm : Evm) : M unit := (* Stores a byte to memory. This also expands the memory, if the memory is @@ -67,33 +81,47 @@ Definition mstore8 : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ (* TODO expression *) - |) in - do* memory.memory_write (| - evm.["memory"], - start_position, - normalized_bytes_value - |) in - (* TODO statement *) - + ]] 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 : M unit := +Definition mload (evm : Evm) : M unit := (* Load word from memory. @@ -103,35 +131,47 @@ Definition mload : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.memory_read_bytes (| - evm.["memory"], - start_position, - ethereum_types.numeric.U256 (| - (* 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 - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition msize : M unit := +Definition msize (evm : Evm) : M unit := (* Push the size of active memory in bytes onto the stack. @@ -142,17 +182,21 @@ Definition msize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["memory"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/dao_fork/vm/instructions/stack.v index 5142bf11c3..aa06094c40 100644 --- a/coq/ethereum/dao_fork/vm/instructions/stack.v +++ b/coq/ethereum/dao_fork/vm/instructions/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM stack related instructions. Require functools. Require ethereum_types.numeric. -Require dao_fork.vm.exceptions. -Require dao_fork.vm.gas. -Require dao_fork.vm.memory. +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 : M unit := +Definition pop (evm : Evm) : M unit := (* Remove item from stack. @@ -28,18 +30,22 @@ Definition pop : M unit := The current EVM frame. *) - do* stack.["pop"] (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in + |) ]] in (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition push_n : M unit := +Definition push_n (evm : Evm) (num_bytes : int) : M unit := (* Pushes a N-byte immediate onto the stack. @@ -54,29 +60,33 @@ Definition push_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - evm.["code"], - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - num_bytes + |) ]] 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 - do* stack.["push"] (| - evm.["stack"], - data_to_push - |) in - (* TODO statement *) - - -Definition dup_n : M unit := + |) 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. @@ -91,20 +101,26 @@ Definition dup_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - let* data_to_duplicate := (* TODO expression *) in - do* stack.["push"] (| - evm.["stack"], - data_to_duplicate - |) 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 : M unit := +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. @@ -123,11 +139,15 @@ Definition swap_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - (* 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/storage.v b/coq/ethereum/dao_fork/vm/instructions/storage.v index 4bec3f185c..9abde01736 100644 --- a/coq/ethereum/dao_fork/vm/instructions/storage.v +++ b/coq/ethereum/dao_fork/vm/instructions/storage.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Storage Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM storage related instructions. *) Require ethereum_types.numeric. -Require dao_fork.state. -Require dao_fork.vm.gas. -Require dao_fork.vm.stack. +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 : M unit := +Definition sload (evm : Evm) : M unit := (* Loads to the stack, the value corresponding to a certain key from the storage of the current account. @@ -28,28 +30,36 @@ Definition sload : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_SLOAD - |) in - let* value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sstore (evm : Evm) : M unit := (* Stores a value at a certain key in the current context's storage. @@ -59,30 +69,40 @@ Definition sstore : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in - let* current_value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in + |) 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - do* state.set_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key, - new_value - |) in - (* TODO statement *) - + 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.v b/coq/ethereum/dao_fork/vm/instructions/system.v index 3639a4aa26..d62c357948 100644 --- a/coq/ethereum/dao_fork/vm/instructions/system.v +++ b/coq/ethereum/dao_fork/vm/instructions/system.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) System Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,14 +15,15 @@ Implementations of the EVM system related instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require dao_fork.fork_types. -Require dao_fork.state. -Require dao_fork.utils.address. -Require dao_fork.vm.gas. -Require dao_fork.vm.memory. -Require dao_fork.vm.stack. +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 : M unit := +Definition create (evm : Evm) : M unit := (* Creates a new account with associated code. @@ -31,43 +33,65 @@ Definition create : M unit := The current EVM frame. *) (* TODO statement *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - let* create_message_gas := evm.["gas_left"] in + |) ]] 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 *) - let* sender_address := evm.["message"].["current_target"] in - let* sender := state.get_account (| - evm.["env"].["state"], - sender_address - |) in - let* contract_address := utils.address.compute_contract_address (| - evm.["message"].["current_target"], - state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["nonce"] - |) in - (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition return_ : M unit := +Definition return_ (evm : Evm) : M unit := (* Halts execution returning output data. @@ -76,65 +100,83 @@ Definition return_ : M unit := evm : The current EVM frame. *) - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) + |) ]] 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 : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_input_start_position, - memory_input_size - |) in - let* code := state.get_account (| - evm.["env"].["state"], - code_address - |).["code"] in - let* child_message := Message (| + 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 - let* child_evm := process_message (| - child_message, - evm.["env"] - |) in + |) 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 *) - let* actual_output_size := min (| - memory_output_size, - ethereum_types.numeric.U256 (| - len (| - child_evm.["output"] + 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 - do* memory.memory_write (| - evm.["memory"], + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), memory_output_start_position, (* TODO expression *) - |) in + |) ]] in + M.pure tt. - -Definition call : M unit := +Definition call (evm : Evm) : M unit := (* Message-call into an account. @@ -143,55 +185,81 @@ Definition call : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* message_call_gas := gas.calculate_message_call_gas (| - evm.["env"].["state"], - gas, - to, - value - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition callcode (evm : Evm) : M unit := (* Message-call into this account with alternative account’s code. @@ -200,56 +268,84 @@ Definition callcode : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* to := evm.["message"].["current_target"] in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* message_call_gas := gas.calculate_message_call_gas (| - evm.["env"].["state"], - gas, - to, - value - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition selfdestruct (evm : Evm) : M unit := (* Halt execution and register account for later deletion. @@ -258,49 +354,63 @@ Definition selfdestruct : M unit := evm : The current EVM frame. *) - let* beneficiary := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* gas_cost := gas.GAS_ZERO in - let* originator := evm.["message"].["current_target"] in - let* refunded_accounts := evm.["accounts_to_delete"] in - let* parent_evm := evm.["message"].["parent_evm"] in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - let* beneficiary_balance := state.get_account (| - evm.["env"].["state"], - beneficiary - |).["balance"] in - let* originator_balance := state.get_account (| - evm.["env"].["state"], - originator - |).["balance"] in - do* state.set_account_balance (| - evm.["env"].["state"], - beneficiary, + 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 (| - evm.["env"].["state"], - originator, - ethereum_types.numeric.U256 (| - (* 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* evm.["accounts_to_delete"].["add"] (| - originator - |) in + |) ]] 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 : M unit := +Definition delegatecall (evm : Evm) : M unit := (* Message-call into an account. @@ -309,49 +419,69 @@ Definition delegatecall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - gas, - evm.["message"].["value"], - evm.["message"].["caller"], - evm.["message"].["current_target"], - code_address, - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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.v b/coq/ethereum/dao_fork/vm/interpreter.v index 944cae5883..4c01fccc89 100644 --- a/coq/ethereum/dao_fork/vm/interpreter.v +++ b/coq/ethereum/dao_fork/vm/interpreter.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Interpreter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +18,18 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.trace. -Require dao_fork.blocks. -Require dao_fork.fork_types. -Require dao_fork.state. -Require dao_fork.vm. -Require dao_fork.vm.gas. -Require dao_fork.vm.precompiled_contracts.mapping. -Require dao_fork.vm.exceptions. -Require dao_fork.vm.instructions. -Require dao_fork.vm.runtime. - -Definition process_message_call : M unit := +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`. @@ -47,19 +49,21 @@ Definition process_message_call : M unit := *) (* TODO statement *) (* TODO statement *) - let* tx_end := ethereum.trace.TransactionEnd (| - (* TODO expression *), - evm.["output"], - evm.["error"] - |) in - do* ethereum.trace.evm_trace (| - evm, - tx_end - |) in + 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 : M unit := +Definition process_create_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -75,22 +79,24 @@ Definition process_create_message : M unit := evm: :py:class:`~ethereum.dao_fork.vm.Evm` Items containing execution specific objects. *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.destroy_storage (| - env.["state"], - message.["current_target"] - |) in - let* evm := process_message (| - message, - env - |) in + 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 : M unit := +Definition process_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -107,23 +113,25 @@ Definition process_message : M unit := Items containing execution specific objects *) (* TODO statement *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.touch_account (| - env.["state"], - message.["current_target"] - |) in + 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 *) - let* evm := execute_code (| - message, - env - |) in + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition execute_code : M unit := +Definition execute_code (message : Message) (env : Environment) : M Evm := (* Executes bytecode present in the `message`. @@ -139,13 +147,19 @@ Definition execute_code : M unit := evm: `ethereum.vm.EVM` Items containing execution specific objects *) - let* code := message.["code"] in - let* valid_jump_destinations := runtime.get_valid_jump_destinations (| - code - |) in - let* evm := Evm (| - - |) in + 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.v b/coq/ethereum/dao_fork/vm/memory.v index 94b6a44639..88b516318f 100644 --- a/coq/ethereum/dao_fork/vm/memory.v +++ b/coq/ethereum/dao_fork/vm/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.byte. -Definition memory_write : M unit := +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := (* Writes to memory. @@ -30,9 +31,9 @@ Definition memory_write : M unit := Data to write to memory. *) (* TODO assignment *) + M.pure tt. - -Definition memory_read_bytes : M unit := +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := (* Read bytes from memory. @@ -51,9 +52,9 @@ Definition memory_read_bytes : M unit := Data read from memory. *) (* TODO statement *) + M.pure tt. - -Definition buffer_read : M unit := +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := (* Read bytes from a buffer. Padding with zeros if necessary. @@ -72,4 +73,4 @@ Definition buffer_read : M unit := Data read from memory. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/precompiled_contracts/__init__.v b/coq/ethereum/dao_fork/vm/precompiled_contracts/__init__.v index 1b69820379..1b2d6cca57 100644 --- a/coq/ethereum/dao_fork/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,4 +14,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require dao_fork.utils.hexadecimal. +Require ethereum.dao_fork.utils.hexadecimal. diff --git a/coq/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.v index 13c3dec3b8..b3b37058be 100644 --- a/coq/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.v +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,11 +17,11 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require dao_fork.vm. -Require dao_fork.vm.gas. -Require dao_fork.vm.memory. +Require ethereum.dao_fork.vm. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.memory. -Definition ecrecover : M unit := +Definition ecrecover (evm : Evm) : M unit := (* Decrypts the address using elliptic curve DSA recovery mechanism and writes the address to output. @@ -30,64 +31,80 @@ Definition ecrecover : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* message_hash_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* message_hash := ethereum.crypto.hash.Hash32 (| - message_hash_bytes - |) in - let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + ethereum_types.numeric.U256 ~(| + 32 |) - |) - |) in - let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 + ]] 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 *) - let* address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/dao_fork/vm/precompiled_contracts/identity.v index 4a985124fa..d65c4f900a 100644 --- a/coq/ethereum/dao_fork/vm/precompiled_contracts/identity.v +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/identity.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,10 @@ Implementation of the `IDENTITY` precompiled contract. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require dao_fork.vm. -Require dao_fork.vm.gas. +Require ethereum.dao_fork.vm. +Require ethereum.dao_fork.vm.gas. -Definition identity : M unit := +Definition identity (evm : Evm) : M unit := (* Writes the message data to output. @@ -26,11 +27,15 @@ Definition identity : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/precompiled_contracts/mapping.v b/coq/ethereum/dao_fork/vm/precompiled_contracts/mapping.v index 83c8947d22..f3b02e3260 100644 --- a/coq/ethereum/dao_fork/vm/precompiled_contracts/mapping.v +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/mapping.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,8 +14,9 @@ Mapping of precompiled contracts their implementations. *) Require typing. -Require dao_fork.fork_types. -Require dao_fork.vm.precompiled_contracts.ecrecover. -Require dao_fork.vm.precompiled_contracts.identity. -Require dao_fork.vm.precompiled_contracts.ripemd160. -Require dao_fork.vm.precompiled_contracts.sha256. +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.v b/coq/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.v index bc5e73dd3c..fe2c66bbe6 100644 --- a/coq/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.v +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `RIPEMD160` precompiled contract. *) -Definition ripemd160 : M unit := +Definition ripemd160 (evm : Evm) : M unit := (* Writes the ripemd160 hash to output. @@ -22,21 +23,29 @@ Definition ripemd160 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 - let* hash_bytes := hashlib.["new"] (| - (* TODO expression *), - data - |).["digest"] (| - - |) in - let* padded_hash := left_pad_zero_bytes (| - hash_bytes, - (* TODO expression *) - |) in + |) ]] 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.v b/coq/ethereum/dao_fork/vm/precompiled_contracts/sha256.v index da6972d411..3ba3ffe7aa 100644 --- a/coq/ethereum/dao_fork/vm/precompiled_contracts/sha256.v +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/sha256.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `SHA256` precompiled contract. *) -Definition sha256 : M unit := +Definition sha256 (evm : Evm) : M unit := (* Writes the sha256 hash to output. @@ -22,11 +23,15 @@ Definition sha256 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/runtime.v b/coq/ethereum/dao_fork/vm/runtime.v index ac92e20add..308e435285 100644 --- a/coq/ethereum/dao_fork/vm/runtime.v +++ b/coq/ethereum/dao_fork/vm/runtime.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Runtime Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Runtime related operations used while executing EVM code. Require typing. Require ethereum_types.numeric. -Require dao_fork.vm.instructions. +Require ethereum.dao_fork.vm.instructions. -Definition get_valid_jump_destinations : M unit := +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := (* Analyze the evm code to obtain the set of valid jump destinations. @@ -38,12 +39,16 @@ Definition get_valid_jump_destinations : M unit := valid_jump_destinations: `Set[Uint]` The set of valid jump destinations in the code. *) - let* valid_jump_destinations := set (| - - |) in - let* pc := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/dao_fork/vm/stack.v index ba1052d24e..77380a95d6 100644 --- a/coq/ethereum/dao_fork/vm/stack.v +++ b/coq/ethereum/dao_fork/vm/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Implementation of the stack operators for the EVM. Require typing. Require ethereum_types.numeric. -Require dao_fork.vm.exceptions. +Require ethereum.dao_fork.vm.exceptions. -Definition pop : M unit := +Definition pop (stack : (* TODO type *)) : M U256 := (* Pops the top item off of `stack`. @@ -33,9 +34,9 @@ Definition pop : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition push : M unit := +Definition push (stack : (* TODO type *)) (value : U256) : M unit := (* Pushes `value` onto `stack`. @@ -50,4 +51,4 @@ Definition push : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/ethash.v b/coq/ethereum/ethash.v index cd1be88eed..39aaf41d0f 100644 --- a/coq/ethereum/ethash.v +++ b/coq/ethereum/ethash.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethash is a proof-of-work algorithm designed to be [ASIC] resistant through [memory hardness][mem-hard]. @@ -32,7 +33,7 @@ Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Definition epoch : M unit := +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. @@ -45,9 +46,9 @@ Definition epoch : M unit := [`generate_dataset`]: ref:ethereum.ethash.generate_dataset *) (* TODO statement *) + M.pure tt. - -Definition cache_size : M unit := +Definition cache_size (block_number : Uint) : M Uint := (* Obtain the cache size (in bytes) of the epoch to which `block_number` belongs. @@ -65,13 +66,17 @@ Definition cache_size : M unit := [`CACHE_EPOCH_GROWTH_SIZE`]: ref:ethereum.ethash.CACHE_EPOCH_GROWTH_SIZE [`generate_cache`]: ref:ethereum.ethash.generate_cache *) - let* size := (* TODO expression *) in - (* TODO statement *) + 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 : M unit := +Definition dataset_size (block_number : Uint) : M Uint := (* Obtain the dataset size (in bytes) of the epoch to which `block_number` belongs. @@ -91,28 +96,36 @@ Definition dataset_size : M unit := [`generate_dataset`]: ref:ethereum.ethash.generate_dataset [`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item *) - let* size := (* TODO expression *) in - (* TODO statement *) + 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 : M unit := +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 *) - let* epoch_number := epoch (| - block_number - |) in - let* seed := (* TODO expression *) in + 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 : M unit := +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. @@ -125,20 +138,28 @@ Definition generate_cache : M unit := [`generate_dataset`]: ref:ethereum.ethash.generate_dataset [RandMemoHash]: http://www.hashcash.org/papers/memohash.pdf *) - let* seed := generate_seed (| - block_number - |) in - let* cache_size_bytes := cache_size (| - block_number - |) in - let* cache_size_words := (* TODO expression *) in - let* cache := (* TODO expression *) in + 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 : M unit := +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 @@ -154,11 +175,13 @@ Definition fnv : M unit := [FNV]: https://w.wiki/XKZ [FNV-1]: http://www.isthe.com/chongo/tech/comp/fnv/#FNV-1 *) - let* result := (* TODO expression *) in + do* M.assign "result" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition fnv_hash : M unit := +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`]. @@ -168,9 +191,9 @@ Definition fnv_hash : M unit := [`fnv`]: ref:ethereum.ethash.fnv *) (* TODO statement *) + M.pure tt. - -Definition generate_dataset_item : M unit := +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 @@ -183,24 +206,30 @@ Definition generate_dataset_item : M unit := [`generate_dataset`]: ref:ethereum.ethash.generate_dataset [`generate_cache`]: ref:ethereum.ethash.generate_cache *) - let* mix := ethereum.crypto.hash.keccak512 (| - (* TODO expression *).["to_le_bytes64"] (| - - |) - |) in - let* mix_integers := ethereum.utils.numeric.le_bytes_to_uint32_sequence (| - mix - |) in + 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 *) - let* mix := ethereum.crypto.hash.Hash64 (| - ethereum.utils.numeric.le_uint32_sequence_to_bytes (| - mix_integers - |) - |) in + 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 : M unit := +Definition generate_dataset (block_number : Uint) : M (* TODO type *) := (* Generate the full dataset for the block identified by `block_number`. @@ -210,9 +239,9 @@ Definition generate_dataset : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition hashimoto : M unit := +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. @@ -234,32 +263,48 @@ Definition hashimoto : M unit := [RLP hash]: ref:ethereum.rlp.rlp_hash [`dataset_size`]: ref:ethereum.ethash.dataset_size *) - let* nonce_le := bytes (| - reversed (| - nonce - |) - |) in - let* seed_hash := ethereum.crypto.hash.keccak512 (| - (* TODO expression *) - |) in - let* seed_head := ethereum_types.numeric.U32.["from_le_bytes"] (| - (* TODO expression *) - |) in - let* rows := (* TODO expression *) in - let* mix := (* TODO expression *) in + 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 *) - let* compressed_mix := (* TODO expression *) in + do* M.assign "compressed_mix" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* mix_digest := ethereum.utils.numeric.le_uint32_sequence_to_bytes (| - compressed_mix - |) in - let* result := ethereum.crypto.hash.keccak256 (| - (* TODO expression *) - |) in + 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 : M unit := +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. @@ -284,4 +329,4 @@ Definition hashimoto_light : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/exceptions.v b/coq/ethereum/exceptions.v index ff2a9d09cd..ab1fc99a54 100644 --- a/coq/ethereum/exceptions.v +++ b/coq/ethereum/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Error types common across all Ethereum forks. *) diff --git a/coq/ethereum/fork_criteria.v b/coq/ethereum/fork_criteria.v index 6e2fcf37f3..0fb15ee79d 100644 --- a/coq/ethereum/fork_criteria.v +++ b/coq/ethereum/fork_criteria.v @@ -1,3 +1,4 @@ +(* Generated *) (* Activation criteria for forks. diff --git a/coq/ethereum/frontier/__init__.v b/coq/ethereum/frontier/__init__.v index 68355e6ddd..1f5a54f0e0 100644 --- a/coq/ethereum/frontier/__init__.v +++ b/coq/ethereum/frontier/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Frontier is the first production-ready iteration of the Ethereum protocol. *) diff --git a/coq/ethereum/frontier/blocks.v b/coq/ethereum/frontier/blocks.v index 0a4788712a..4e022f9c09 100644 --- a/coq/ethereum/frontier/blocks.v +++ b/coq/ethereum/frontier/blocks.v @@ -1,3 +1,4 @@ +(* 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 @@ -14,6 +15,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. -Require frontier.fork_types. -Require frontier.transactions. +Require ethereum.crypto.hash. +Require ethereum.frontier.fork_types. +Require ethereum.frontier.transactions. diff --git a/coq/ethereum/frontier/bloom.v b/coq/ethereum/frontier/bloom.v index 82669c6c5e..2f8df625d6 100644 --- a/coq/ethereum/frontier/bloom.v +++ b/coq/ethereum/frontier/bloom.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Logs Bloom ^^^^^^^^^^^^^^^^^^^ @@ -19,10 +20,10 @@ eliminating blocks and receipts from their search. Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require frontier.blocks. -Require frontier.fork_types. +Require ethereum.frontier.blocks. +Require ethereum.frontier.fork_types. -Definition add_to_bloom : M unit := +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := (* Add a bloom entry to the bloom filter (`bloom`). @@ -37,13 +38,15 @@ Definition add_to_bloom : M unit := bloom_entry : An entry which is to be added to bloom filter. *) - let* hash := ethereum.crypto.hash.keccak256 (| - bloom_entry - |) in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition logs_bloom : M unit := +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := (* Obtain the logs bloom from a list of log entries. @@ -63,4 +66,4 @@ Definition logs_bloom : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/frontier/fork.v b/coq/ethereum/frontier/fork.v index c8fcbddea6..b917c923c5 100644 --- a/coq/ethereum/frontier/fork.v +++ b/coq/ethereum/frontier/fork.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^ @@ -20,16 +21,18 @@ Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.ethash. Require ethereum.exceptions. -Require frontier.blocks. -Require frontier.bloom. -Require frontier.fork_types. -Require frontier.state. -Require frontier.transactions. -Require frontier.trie. -Require frontier.utils.message. -Require frontier.vm.interpreter. - -Definition apply_fork : M unit := +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. @@ -49,9 +52,9 @@ Definition apply_fork : M unit := Upgraded block chain object for this hard fork. *) (* TODO statement *) + M.pure tt. - -Definition get_last_256_block_hashes : M unit := +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. @@ -71,22 +74,28 @@ Definition get_last_256_block_hashes : M unit := recent_block_hashes : `List[Hash32]` Hashes of the recent 256 blocks in order of increasing block number. *) - let* recent_blocks := (* TODO expression *) in - (* TODO statement *) - let* recent_block_hashes := (* TODO expression *) in - (* TODO statement *) - let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *).["header"] - |) - |) in - do* recent_block_hashes.["append"] (| - most_recent_block_hash - |) in - (* TODO statement *) - - -Definition state_transition : M unit := + 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. @@ -108,41 +117,45 @@ Definition state_transition : M unit := block : Block to apply to `chain`. *) - let* parent_header := (* TODO expression *).["header"] in - do* validate_header (| - block.["header"], - parent_header - |) in - do* validate_ommers (| - block.["ommers"], - block.["header"], + 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 - let* apply_body_output := apply_body (| - chain.["state"], - get_last_256_block_hashes (| - chain - |), - block.["header"].["coinbase"], - block.["header"].["number"], - block.["header"].["gas_limit"], - block.["header"].["timestamp"], - block.["header"].["difficulty"], - block.["transactions"], - block.["ommers"] - |) in + |) ]] 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* chain.["blocks"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| block - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition validate_header : M unit := +Definition validate_header (header : Header) (parent_header : Header) : M unit := (* Verifies a block header. @@ -164,25 +177,29 @@ Definition validate_header : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* block_difficulty := calculate_block_difficulty (| - header.["number"], - header.["timestamp"], - parent_header.["timestamp"], - parent_header.["difficulty"] - |) in + 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 *) - let* block_parent_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - parent_header - |) - |) in + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in (* TODO statement *) - do* validate_proof_of_work (| + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| header - |) in - + |) ]] in + M.pure tt. -Definition generate_header_hash_for_pow : M unit := +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. @@ -205,11 +222,13 @@ Definition generate_header_hash_for_pow : M unit := hash : `Hash32` The PoW valid rlp hash of the passed in header. *) - let* header_data_without_pow_artefacts := (* TODO expression *) in + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition validate_proof_of_work : M unit := +Definition validate_proof_of_work (header : Header) : M unit := (* Validates the Proof of Work constraints. @@ -224,19 +243,25 @@ Definition validate_proof_of_work : M unit := header : Header of interest. *) - let* header_hash := generate_header_hash_for_pow (| - header - |) in - let* cache := ethereum.ethash.generate_cache (| - header.["number"] - |) in + 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 *) - let* limit := (* TODO expression *) in + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition check_transaction : M unit := +Definition check_transaction (tx : Transaction) (gas_available : Uint) : M Address := (* Check if the transaction is includable in the block. @@ -258,13 +283,15 @@ Definition check_transaction : M unit := If the transaction is not includable. *) (* TODO statement *) - let* sender_address := recover_sender (| - tx - |) in + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + tx + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition make_receipt : M unit := +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. @@ -285,13 +312,15 @@ Definition make_receipt : M unit := receipt : The receipt for the transaction. *) - let* receipt := blocks.Receipt (| + do* M.assign "receipt" [[ + blocks.Receipt ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition apply_body : M unit := +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. @@ -330,25 +359,31 @@ Definition apply_body : M unit := apply_body_output : `ApplyBodyOutput` Output of applying the block body to the state. *) - let* gas_available := block_gas_limit in + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - do* pay_rewards (| + do* [[ M.get_local ~(| "pay_rewards" |) ~(| state, block_number, coinbase, ommers - |) in - let* block_gas_used := (* TODO expression *) in - let* block_logs_bloom := bloom.logs_bloom (| - block_logs - |) in - (* TODO statement *) - - -Definition validate_ommers : M unit := + |) ]] 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. @@ -370,23 +405,31 @@ Definition validate_ommers : M unit := chain : History and current state. *) - let* block_hash := rlp.["rlp_hash"] (| - block_header - |) in + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* ommers_hashes := (* TODO expression *) in + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* recent_canonical_blocks := (* TODO expression *) in - let* recent_canonical_block_hashes := (* TODO expression *) in + 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 : M unit := +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. @@ -412,21 +455,25 @@ Definition pay_rewards : M unit := ommers : List of ommers mentioned in the current block. *) - let* ommer_count := ethereum_types.numeric.U256 (| - len (| - ommers - |) - |) in - let* miner_reward := (* TODO expression *) in - do* state.create_ether (| + 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, - miner_reward - |) in + M.get_local ~(| "miner_reward" |) + |) ]] in (* TODO statement *) + M.pure tt. - -Definition process_transaction : M unit := +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := (* Execute a transaction against the provided environment. @@ -454,67 +501,95 @@ Definition process_transaction : M unit := Logs generated during execution. *) (* TODO statement *) - let* sender := env.["origin"] in - let* sender_account := state.get_account (| - env.["state"], - sender - |) in - let* gas_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* gas := (* TODO expression *) in - do* state.increment_nonce (| - env.["state"], - sender - |) in - let* sender_balance_after_gas_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - ethereum_types.numeric.U256 (| - sender_balance_after_gas_fee + 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 - let* message := utils.message.prepare_message (| - sender, - tx.["to"], - tx.["value"], - tx.["data"], - gas, - env - |) in - let* output := vm.interpreter.process_message_call (| - message, - env - |) in - let* gas_used := (* TODO expression *) in - let* gas_refund := min (| - (* TODO expression *), - ethereum_types.numeric.Uint (| - output.["refund_counter"] - |) - |) in - let* gas_refund_amount := (* TODO expression *) in - let* transaction_fee := (* TODO expression *) in - let* total_gas_used := (* TODO expression *) in - let* sender_balance_after_refund := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - sender_balance_after_refund - |) in - let* coinbase_balance_after_mining_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - env.["coinbase"], - coinbase_balance_after_mining_fee - |) in - (* TODO statement *) - (* TODO statement *) - - -Definition validate_transaction : M unit := + |) ]] 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. @@ -542,9 +617,9 @@ Definition validate_transaction : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition calculate_intrinsic_cost : M unit := +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := (* Calculates the gas that is charged before execution is started. @@ -567,12 +642,14 @@ Definition calculate_intrinsic_cost : M unit := verified : `ethereum.base_types.Uint` The intrinsic cost of the transaction. *) - let* data_cost := (* TODO expression *) in + do* M.assign "data_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition recover_sender : M unit := +Definition recover_sender (tx : Transaction) : M Address := (* Extracts the sender address from a transaction. @@ -596,18 +673,20 @@ Definition recover_sender : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* public_key := ethereum.crypto.elliptic_curve.secp256k1_recover (| - r, - s, - (* TODO expression *), - signing_hash (| - tx - |) - |) in + 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 : M unit := +Definition signing_hash (tx : Transaction) : M Hash32 := (* Compute the hash of a transaction used in the signature. @@ -626,9 +705,9 @@ Definition signing_hash : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition compute_header_hash : M unit := +Definition compute_header_hash (header : Header) : M Hash32 := (* Computes the hash of a block header. @@ -661,9 +740,9 @@ Definition compute_header_hash : M unit := Hash of the header. *) (* TODO statement *) + M.pure tt. - -Definition check_gas_limit : M unit := +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := (* Validates the gas limit for a block. @@ -691,14 +770,16 @@ Definition check_gas_limit : M unit := check : `bool` True if gas limit constraints are satisfied, False otherwise. *) - let* max_adjustment_delta := (* TODO expression *) in + 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 : M unit := +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. @@ -728,9 +809,13 @@ Definition calculate_block_difficulty : M unit := difficulty : `ethereum.base_types.Uint` Computed difficulty for a block. *) - let* max_adjustment_delta := (* TODO expression *) in + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* num_bomb_periods := (* TODO expression *) in + 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.v b/coq/ethereum/frontier/fork_types.v index 14de99d5e5..d84cffdf45 100644 --- a/coq/ethereum/frontier/fork_types.v +++ b/coq/ethereum/frontier/fork_types.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Types ^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. +Require ethereum.__init__. +Require ethereum.crypto.hash. -Definition encode_account : M unit := +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := (* Encode `Account` dataclass. @@ -26,4 +28,4 @@ Definition encode_account : M unit := encoded without providing a storage root. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/frontier/state.v b/coq/ethereum/frontier/state.v index bc6d2698de..e4a5b7d0cb 100644 --- a/coq/ethereum/frontier/state.v +++ b/coq/ethereum/frontier/state.v @@ -1,3 +1,4 @@ +(* Generated *) (* State ^^^^^ @@ -22,10 +23,10 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require frontier.fork_types. -Require frontier.trie. +Require ethereum.frontier.fork_types. +Require ethereum.frontier.trie. -Definition close_state : M unit := +Definition close_state (state : State) : M unit := (* Free resources held by the state. Used by optimized implementations to release file descriptors. @@ -33,9 +34,9 @@ Definition close_state : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition begin_transaction : M unit := +Definition begin_transaction (state : State) : M unit := (* Start a state transaction. @@ -47,12 +48,12 @@ Definition begin_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition commit_transaction : M unit := +Definition commit_transaction (state : State) : M unit := (* Commit a state transaction. @@ -61,12 +62,12 @@ Definition commit_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["pop"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| - |) in + |) ]] in + M.pure tt. - -Definition rollback_transaction : M unit := +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. @@ -77,9 +78,9 @@ Definition rollback_transaction : M unit := The state. *) (* TODO assignment *) + M.pure tt. - -Definition get_account : M unit := +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. @@ -99,14 +100,16 @@ Definition get_account : M unit := account : `Account` Account at address. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition get_account_optional : M unit := +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. @@ -123,14 +126,16 @@ Definition get_account_optional : M unit := account : `Account` Account at address. *) - let* account := trie.trie_get (| - state.["_main_trie"], - address - |) in + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition set_account : M unit := +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()`). @@ -144,14 +149,14 @@ Definition set_account : M unit := account : `Account` Account to set at address. *) - do* trie.trie_set (| - state.["_main_trie"], + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), address, account - |) in - + |) ]] in + M.pure tt. -Definition destroy_account : M unit := +Definition destroy_account (state : State) (address : Address) : M unit := (* Completely remove the account at `address` and all of its storage. @@ -166,18 +171,18 @@ Definition destroy_account : M unit := address : `Address` Address of account to destroy. *) - do* destroy_storage (| + do* [[ M.get_local ~(| "destroy_storage" |) ~(| state, address - |) in - do* set_account (| + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - (* TODO expression *) - |) in - + tt + |) ]] in + M.pure tt. -Definition destroy_storage : M unit := +Definition destroy_storage (state : State) (address : Address) : M unit := (* Completely remove the storage at `address`. @@ -189,9 +194,9 @@ Definition destroy_storage : M unit := Address of account whose storage is to be deleted. *) (* TODO statement *) + M.pure tt. - -Definition get_storage : M unit := +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. @@ -210,19 +215,23 @@ Definition get_storage : M unit := value : `U256` Value at the key. *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition set_storage : M unit := +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. @@ -239,19 +248,21 @@ Definition set_storage : M unit := Value to set at the key. *) (* TODO statement *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - do* trie.trie_set (| - trie, + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), key, value - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition storage_root : M unit := +Definition storage_root (state : State) (address : Address) : M Root := (* Calculate the storage root of an account. @@ -269,9 +280,9 @@ Definition storage_root : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition state_root : M unit := +Definition state_root (state : State) : M Root := (* Calculate the state root. @@ -288,9 +299,9 @@ Definition state_root : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition account_exists : M unit := +Definition account_exists (state : State) (address : Address) : M bool := (* Checks if an account exists in the state trie @@ -307,9 +318,9 @@ Definition account_exists : M unit := True if account exists in the state trie, False otherwise *) (* TODO statement *) + M.pure tt. - -Definition account_has_code_or_nonce : M unit := +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := (* Checks if an account has non zero nonce or non empty code @@ -326,49 +337,51 @@ Definition account_has_code_or_nonce : M unit := True if if an account has non zero nonce or non empty code, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition modify_state : M unit := +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := (* Modify an `Account` in the `State`. *) - do* set_account (| + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - ethereum_types.frozen.modify (| - get_account (| + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| state, address |), f |) - |) in + |) ]] in + M.pure tt. - -Definition move_ether : M unit := +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := (* Move funds between accounts. *) (* TODO statement *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, sender_address, - reduce_sender_balance - |) in - do* modify_state (| + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| state, recipient_address, - increase_recipient_balance - |) in - + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. -Definition set_account_balance : M unit := +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := (* Sets the balance of an account. @@ -384,14 +397,14 @@ Definition set_account_balance : M unit := The amount that needs to set in balance. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - set_balance - |) in + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. - -Definition touch_account : M unit := +Definition touch_account (state : State) (address : Address) : M unit := (* Initializes an account to state. @@ -404,9 +417,9 @@ Definition touch_account : M unit := The address of the account that need to initialised. *) (* TODO statement *) + M.pure tt. - -Definition increment_nonce : M unit := +Definition increment_nonce (state : State) (address : Address) : M unit := (* Increments the nonce of an account. @@ -419,14 +432,14 @@ Definition increment_nonce : M unit := Address of the account whose nonce needs to be incremented. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_nonce - |) in + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. - -Definition set_code : M unit := +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := (* Sets Account code. @@ -442,14 +455,14 @@ Definition set_code : M unit := The bytecode that needs to be set. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - write_code - |) in - + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. -Definition create_ether : M unit := +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := (* Add newly created ether to an account. @@ -463,9 +476,9 @@ Definition create_ether : M unit := The amount of ether to be added to the account of interest. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_balance - |) in - + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. diff --git a/coq/ethereum/frontier/transactions.v b/coq/ethereum/frontier/transactions.v index 42ba7f2ca3..b3bdb570f6 100644 --- a/coq/ethereum/frontier/transactions.v +++ b/coq/ethereum/frontier/transactions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, @@ -9,4 +10,4 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require frontier.fork_types. +Require ethereum.frontier.fork_types. diff --git a/coq/ethereum/frontier/trie.v b/coq/ethereum/frontier/trie.v index 548de91e1c..6b8953f256 100644 --- a/coq/ethereum/frontier/trie.v +++ b/coq/ethereum/frontier/trie.v @@ -1,3 +1,4 @@ +(* Generated *) (* State Trie ^^^^^^^^^^ @@ -14,7 +15,7 @@ The state trie is the structure responsible for storing *) -Definition encode_internal_node : M unit := +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 @@ -35,22 +36,24 @@ Definition encode_internal_node : M unit := *) (* TODO statement *) (* TODO statement *) - let* encoded := rlp.["encode"] (| - unencoded - |) in + 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 : M unit := +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 : M unit := +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. @@ -66,9 +69,9 @@ Definition copy_trie : M unit := A copy of the trie. *) (* TODO statement *) + M.pure tt. - -Definition trie_set : M unit := +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := (* Stores an item in a Merkle Trie. @@ -85,9 +88,9 @@ Definition trie_set : M unit := Node to insert at `key`. *) (* TODO statement *) + M.pure tt. - -Definition trie_get : M unit := +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := (* Gets an item from the Merkle Trie. @@ -106,17 +109,17 @@ Definition trie_get : M unit := Node at `key` in the trie. *) (* TODO statement *) + M.pure tt. - -Definition common_prefix_length : M unit := +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 : M unit := +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := (* Compresses nibble-list into a standard byte array with a flag. @@ -150,14 +153,16 @@ Definition nibble_list_to_compact : M unit := compressed : `bytearray` Compact byte array. *) - let* compact := bytearray (| + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition bytes_to_nibble_list : M unit := +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := (* Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). @@ -171,14 +176,16 @@ Definition bytes_to_nibble_list : M unit := nibble_list : `Bytes` The `Bytes` in nibble-list format. *) - let* nibble_list := bytearray (| - (* TODO expression *) - |) in + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _prepare_trie : M unit := +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. @@ -199,9 +206,9 @@ Definition _prepare_trie : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition root : M unit := +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := (* Computes the root of a modified merkle patricia trie (MPT). @@ -219,22 +226,26 @@ Definition root : M unit := root : `.fork_types.Root` MPT root of the underlying key-value pairs. *) - let* obj := _prepare_trie (| - trie, - get_storage_root - |) in - let* root_node := encode_internal_node (| - patricialize (| - obj, - Uint (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) + M.pure tt. - -Definition patricialize : M unit := +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := (* Structural composition function. @@ -254,21 +265,29 @@ Definition patricialize : M unit := Root node of `obj`. *) (* TODO statement *) - let* arbitrary_key := next (| - iter (| - obj - |) - |) in + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in (* TODO statement *) - let* substring := (* TODO expression *) in - let* prefix_length := len (| - substring - |) in + 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 *) - let* value := (* TODO expression *) in + do* M.assign "value" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/frontier/utils/__init__.v b/coq/ethereum/frontier/utils/__init__.v index beff4482b1..7f30fe939b 100644 --- a/coq/ethereum/frontier/utils/__init__.v +++ b/coq/ethereum/frontier/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions unique to this particular fork. *) diff --git a/coq/ethereum/frontier/utils/address.v b/coq/ethereum/frontier/utils/address.v index 76588f62aa..47863b9c36 100644 --- a/coq/ethereum/frontier/utils/address.v +++ b/coq/ethereum/frontier/utils/address.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require frontier.fork_types. +Require ethereum.__init__. +Require ethereum.frontier.fork_types. -Definition to_address : M unit := +Definition to_address (data : (* TODO type *)) : M Address := (* Convert a Uint or U256 value to a valid address (20 bytes). @@ -33,9 +35,9 @@ Definition to_address : M unit := The obtained address. *) (* TODO statement *) + M.pure tt. - -Definition compute_contract_address : M unit := +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := (* Computes address of the new account that needs to be created. @@ -52,15 +54,21 @@ Definition compute_contract_address : M unit := address: `ethereum.frontier.fork_types.Address` The computed address of the new account. *) - let* computed_address := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *) - |) - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/frontier/utils/hexadecimal.v index 6915da1c3a..5bdfa980bd 100644 --- a/coq/ethereum/frontier/utils/hexadecimal.v +++ b/coq/ethereum/frontier/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ types. *) Require ethereum.utils.hexadecimal. -Require frontier.fork_types. +Require ethereum.frontier.fork_types. -Definition hex_to_root : M unit := +Definition hex_to_root (hex_string : str) : M Root := (* Convert hex string to trie root. @@ -31,9 +32,9 @@ Definition hex_to_root : M unit := Trie root obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bloom : M unit := +Definition hex_to_bloom (hex_string : str) : M Bloom := (* Convert hex string to bloom. @@ -48,9 +49,9 @@ Definition hex_to_bloom : M unit := Bloom obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_address : M unit := +Definition hex_to_address (hex_string : str) : M Address := (* Convert hex string to Address (20 bytes). @@ -65,4 +66,4 @@ Definition hex_to_address : M unit := The address obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/frontier/utils/message.v b/coq/ethereum/frontier/utils/message.v index 5a5df9c686..7fba7a2069 100644 --- a/coq/ethereum/frontier/utils/message.v +++ b/coq/ethereum/frontier/utils/message.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For The Message Data-structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,12 +16,12 @@ Message specific functions used in this frontier version of specification. Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require frontier.fork_types. -Require frontier.state. -Require frontier.vm. -Require frontier.utils.address. +Require ethereum.frontier.fork_types. +Require ethereum.frontier.state. +Require ethereum.frontier.vm. +Require ethereum.frontier.utils.address. -Definition prepare_message : M unit := +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. @@ -50,4 +51,4 @@ Definition prepare_message : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/frontier/vm/__init__.v b/coq/ethereum/frontier/vm/__init__.v index 10896c0c78..42de0686a7 100644 --- a/coq/ethereum/frontier/vm/__init__.v +++ b/coq/ethereum/frontier/vm/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,11 +19,11 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require frontier.blocks. -Require frontier.fork_types. -Require frontier.state. +Require ethereum.frontier.blocks. +Require ethereum.frontier.fork_types. +Require ethereum.frontier.state. -Definition incorporate_child_on_success : M unit := +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of a successful `child_evm` into the parent `evm`. @@ -33,15 +34,21 @@ Definition incorporate_child_on_success : M unit := child_evm : The child evm to incorporate. *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - do* evm.["accounts_to_delete"].["update"] (| - child_evm.["accounts_to_delete"] - |) in + 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 : M unit := +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. @@ -52,5 +59,7 @@ Definition incorporate_child_on_error : M unit := child_evm : The child evm to incorporate. *) - (* 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/frontier/vm/exceptions.v b/coq/ethereum/frontier/vm/exceptions.v index 1784494410..47e26555d5 100644 --- a/coq/ethereum/frontier/vm/exceptions.v +++ b/coq/ethereum/frontier/vm/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Exceptions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/frontier/vm/gas.v b/coq/ethereum/frontier/vm/gas.v index acf1e37bda..0555940bcd 100644 --- a/coq/ethereum/frontier/vm/gas.v +++ b/coq/ethereum/frontier/vm/gas.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Gas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,11 +18,12 @@ Require typing. Require ethereum_types.numeric. Require ethereum.trace. Require ethereum.utils.numeric. -Require frontier.fork_types. -Require frontier.state. -Require frontier.vm.exceptions. +Require ethereum.frontier.fork_types. +Require ethereum.frontier.state. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.exceptions. -Definition charge_gas : M unit := +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := (* Subtracts `amount` from `evm.gas_left`. @@ -33,18 +35,18 @@ Definition charge_gas : M unit := The amount of gas the current operation requires. *) - do* ethereum.trace.evm_trace (| + do* [[ ethereum.trace.evm_trace ~(| evm, - ethereum.trace.GasAndRefund (| - int (| + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| amount |) |) - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_memory_gas_cost : M unit := +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, @@ -60,14 +62,22 @@ Definition calculate_memory_gas_cost : M unit := total_gas_cost : `ethereum.base_types.Uint` The gas cost for storing data in memory. *) - let* size_in_words := (* TODO expression *) in - let* linear_cost := (* TODO expression *) in - let* quadratic_cost := (* TODO expression *) in - let* total_gas_cost := (* TODO expression *) in + 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 : M unit := +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := (* Calculates the gas amount to extend memory @@ -83,22 +93,28 @@ Definition calculate_gas_extend_memory : M unit := ------- extend_memory: `ExtendMemory` *) - let* size_to_extend := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* to_be_paid := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* current_size := ethereum_types.numeric.Uint (| - len (| - memory - |) - |) in + 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 : M unit := +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`. @@ -117,9 +133,17 @@ Definition calculate_message_call_gas : M unit := ------- message_call_gas: `MessageCallGas` *) - let* create_gas_cost := (* TODO expression *) in - let* transfer_gas_cost := (* TODO expression *) in - let* cost := (* TODO expression *) in - let* stipend := (* TODO expression *) in + 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__.v b/coq/ethereum/frontier/vm/instructions/__init__.v index b36b1ebfef..cbd7e7e63a 100644 --- a/coq/ethereum/frontier/vm/instructions/__init__.v +++ b/coq/ethereum/frontier/vm/instructions/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* EVM Instruction Encoding (Opcodes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/frontier/vm/instructions/arithmetic.v b/coq/ethereum/frontier/vm/instructions/arithmetic.v index b606a22e90..68ae8e4ef3 100644 --- a/coq/ethereum/frontier/vm/instructions/arithmetic.v +++ b/coq/ethereum/frontier/vm/instructions/arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,11 @@ Implementations of the EVM Arithmetic instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require frontier.vm.gas. -Require frontier.vm.stack. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.stack. -Definition add : M unit := +Definition add (evm : Evm) : M unit := (* Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -28,27 +30,37 @@ Definition add : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_add"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sub (evm : Evm) : M unit := (* Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -59,27 +71,37 @@ Definition sub : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_sub"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mul (evm : Evm) : M unit := (* Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -90,27 +112,37 @@ Definition mul : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_mul"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition div (evm : Evm) : M unit := (* Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -121,25 +153,33 @@ Definition div : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |) in - let* divisor := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - quotient - |) 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 : M unit := +Definition sdiv (evm : Evm) : M unit := (* Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -150,31 +190,39 @@ Definition sdiv : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* divisor := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - quotient + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mod : M unit := +Definition mod (evm : Evm) : M unit := (* Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -185,25 +233,33 @@ Definition mod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - remainder - |) in + |) ]] 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 : M unit := +Definition smod (evm : Evm) : M unit := (* Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -214,31 +270,39 @@ Definition smod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* y := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - remainder + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition addmod : M unit := +Definition addmod (evm : Evm) : M unit := (* Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -249,34 +313,44 @@ Definition addmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +Definition mulmod (evm : Evm) : M unit := (* Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -287,34 +361,44 @@ Definition mulmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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 : M unit := +Definition exp (evm : Evm) : M unit := (* Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -325,39 +409,53 @@ Definition exp : M unit := The current EVM frame. *) - let* base := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent_bits := exponent.["bit_length"] (| - - |) in - let* exponent_bytes := (* TODO expression *) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - pow (| - base, - exponent, - (* 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 - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition signextend : M unit := +Definition signextend (evm : Evm) : M unit := (* Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -368,20 +466,28 @@ Definition signextend : M unit := The current EVM frame. *) - let* byte_num := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/frontier/vm/instructions/bitwise.v index b4db7dd45a..747ad4ded7 100644 --- a/coq/ethereum/frontier/vm/instructions/bitwise.v +++ b/coq/ethereum/frontier/vm/instructions/bitwise.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Bitwise Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM bitwise instructions. *) Require ethereum_types.numeric. -Require frontier.vm.gas. -Require frontier.vm.stack. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.stack. -Definition bitwise_and : M unit := +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. @@ -27,24 +29,32 @@ Definition bitwise_and : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_or : M unit := + |) ]] 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. @@ -55,24 +65,32 @@ Definition bitwise_or : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_xor : M unit := + |) ]] 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. @@ -83,24 +101,32 @@ Definition bitwise_xor : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_not : M unit := + |) ]] 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. @@ -111,21 +137,27 @@ Definition bitwise_not : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition get_byte : M unit := + |) ]] 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 @@ -137,20 +169,28 @@ Definition get_byte : M unit := The current EVM frame. *) - let* byte_index := stack.pop (| - evm.["stack"] - |) in - let* word := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/frontier/vm/instructions/block.v index cb177ec3f1..53883c35b7 100644 --- a/coq/ethereum/frontier/vm/instructions/block.v +++ b/coq/ethereum/frontier/vm/instructions/block.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Block Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM block instructions. *) Require ethereum_types.numeric. -Require frontier.vm.gas. -Require frontier.vm.stack. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.stack. -Definition block_hash : M unit := +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. @@ -27,27 +29,35 @@ Definition block_hash : M unit := The current EVM frame. *) - let* block_number := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* max_block_number := (* TODO expression *) in + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition coinbase : M unit := +Definition coinbase (evm : Evm) : M unit := (* Push the current block's beneficiary address (address of the block miner) onto the stack. @@ -62,20 +72,24 @@ Definition coinbase : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["coinbase"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition timestamp : M unit := +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. @@ -90,18 +104,22 @@ Definition timestamp : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["env"].["time"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition number (evm : Evm) : M unit := (* Push the current block's number onto the stack. @@ -115,20 +133,24 @@ Definition number : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["number"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition difficulty : M unit := +Definition difficulty (evm : Evm) : M unit := (* Push the current block's difficulty onto the stack. @@ -142,20 +164,24 @@ Definition difficulty : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["difficulty"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_limit : M unit := +Definition gas_limit (evm : Evm) : M unit := (* Push the current block's gas limit onto the stack. @@ -169,15 +195,19 @@ Definition gas_limit : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_limit"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/frontier/vm/instructions/comparison.v index b2ab7fc92a..b8fc0d99b1 100644 --- a/coq/ethereum/frontier/vm/instructions/comparison.v +++ b/coq/ethereum/frontier/vm/instructions/comparison.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Comparison Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM Comparison instructions. *) Require ethereum_types.numeric. -Require frontier.vm.gas. -Require frontier.vm.stack. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.stack. -Definition less_than : M unit := +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. @@ -27,27 +29,37 @@ Definition less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_less_than : M unit := + |) ]] 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. @@ -57,31 +69,41 @@ Definition signed_less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition greater_than : M unit := + |) ]] 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. @@ -92,27 +114,37 @@ Definition greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_greater_than : M unit := + |) ]] 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. @@ -122,31 +154,41 @@ Definition signed_greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition equal : M unit := + |) ]] 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. @@ -157,27 +199,37 @@ Definition equal : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition is_zero : M unit := + |) ]] 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. @@ -188,19 +240,27 @@ Definition is_zero : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/frontier/vm/instructions/control_flow.v index 1576250b1d..8d774a9866 100644 --- a/coq/ethereum/frontier/vm/instructions/control_flow.v +++ b/coq/ethereum/frontier/vm/instructions/control_flow.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Control Flow Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM control flow instructions. *) Require ethereum_types.numeric. -Require frontier.vm.gas. -Require frontier.vm.exceptions. -Require frontier.vm.stack. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.exceptions. +Require ethereum.frontier.vm.stack. -Definition stop : M unit := +Definition stop (evm : Evm) : M unit := (* Stop further execution of EVM code. @@ -29,10 +31,14 @@ Definition stop : M unit := (* TODO statement *) (* TODO statement *) (* TODO assignment *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jump : M unit := +Definition jump (evm : Evm) : M unit := (* Alter the program counter to the location specified by the top of the stack. @@ -43,20 +49,22 @@ Definition jump : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition jumpi : M unit := +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 @@ -68,23 +76,27 @@ Definition jumpi : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* conditional_value := stack.pop (| - evm.["stack"] - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition pc : M unit := +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. @@ -96,20 +108,24 @@ Definition pc : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["pc"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_left : M unit := +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. @@ -121,20 +137,24 @@ Definition gas_left : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["gas_left"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jumpdest : M unit := +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 @@ -147,10 +167,14 @@ Definition jumpdest : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_JUMPDEST - |) in - (* TODO statement *) + |) ]] 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.v b/coq/ethereum/frontier/vm/instructions/environment.v index e5bf97904a..cf2f8aad3f 100644 --- a/coq/ethereum/frontier/vm/instructions/environment.v +++ b/coq/ethereum/frontier/vm/instructions/environment.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,13 +15,14 @@ Implementations of the EVM environment related instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require frontier.state. -Require frontier.utils.address. -Require frontier.vm.memory. -Require frontier.vm.gas. -Require frontier.vm.stack. - -Definition address : M unit := +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. @@ -31,20 +33,24 @@ Definition address : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["current_target"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition balance : M unit := +Definition balance (evm : Evm) : M unit := (* Pushes the balance of the given account onto the stack. @@ -54,27 +60,35 @@ Definition balance : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* balance := state.get_account (| - evm.["env"].["state"], - address - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +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. @@ -86,20 +100,24 @@ Definition origin : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["origin"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition caller : M unit := +Definition caller (evm : Evm) : M unit := (* Pushes the address of the caller onto the stack. @@ -110,20 +128,24 @@ Definition caller : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["caller"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition callvalue : M unit := +Definition callvalue (evm : Evm) : M unit := (* Push the value (in wei) sent with the call onto the stack. @@ -134,18 +156,22 @@ Definition callvalue : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["message"].["value"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition calldataload (evm : Evm) : M unit := (* Push a word (32 bytes) of the input data belonging to the current environment onto the stack. @@ -156,30 +182,38 @@ Definition calldataload : M unit := The current EVM frame. *) - let* start_index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - start_index, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] 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* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - value + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 |) - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition calldatasize : M unit := +Definition calldatasize (evm : Evm) : M unit := (* Push the size of input data in current environment onto the stack. @@ -190,22 +224,26 @@ Definition calldatasize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["message"].["data"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition calldatacopy : M unit := +Definition calldatacopy (evm : Evm) : M unit := (* Copy a portion of the input data in current environment to memory. @@ -218,40 +256,60 @@ Definition calldatacopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* data_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - data_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition codesize (evm : Evm) : M unit := (* Push the size of code running in current environment onto the stack. @@ -262,22 +320,26 @@ Definition codesize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["code"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition codecopy : M unit := +Definition codecopy (evm : Evm) : M unit := (* Copy a portion of the code in current environment to memory. @@ -290,40 +352,60 @@ Definition codecopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["code"], - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition gasprice (evm : Evm) : M unit := (* Push the gas price used in current environment onto the stack. @@ -334,20 +416,24 @@ Definition gasprice : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_price"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition extcodesize : M unit := +Definition extcodesize (evm : Evm) : M unit := (* Push the code size of a given account onto the stack. @@ -357,31 +443,39 @@ Definition extcodesize : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* codesize := ethereum_types.numeric.U256 (| - len (| - state.get_account (| - evm.["env"].["state"], - address - |).["code"] + |) ]] 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 - do* stack.push (| - evm.["stack"], - codesize - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition extcodecopy : M unit := +Definition extcodecopy (evm : Evm) : M unit := (* Copy a portion of an account's code to memory. @@ -391,44 +485,68 @@ Definition extcodecopy : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* code := state.get_account (| - evm.["env"].["state"], - address - |).["code"] in - let* value := vm.memory.buffer_read (| - code, - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/frontier/vm/instructions/keccak.v index e67dbb5979..ceca13d7a4 100644 --- a/coq/ethereum/frontier/vm/instructions/keccak.v +++ b/coq/ethereum/frontier/vm/instructions/keccak.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Keccak Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM keccak instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require frontier.vm.gas. -Require frontier.vm.memory. -Require frontier.vm.stack. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.memory. +Require ethereum.frontier.vm.stack. -Definition keccak : M unit := +Definition keccak (evm : Evm) : M unit := (* Pushes to the stack the Keccak-256 hash of a region of memory. @@ -32,36 +34,56 @@ Definition keccak : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* word_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in - let* hash := ethereum.crypto.hash.keccak256 (| - data - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/frontier/vm/instructions/log.v index 4d9c4d0aef..671f8d43ab 100644 --- a/coq/ethereum/frontier/vm/instructions/log.v +++ b/coq/ethereum/frontier/vm/instructions/log.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Logging Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,12 +15,13 @@ Implementations of the EVM logging instructions. Require functools. Require ethereum_types.numeric. -Require frontier.blocks. -Require frontier.vm.gas. -Require frontier.vm.memory. -Require frontier.vm.stack. +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 : M unit := +Definition log_n (evm : Evm) (num_topics : U256) : M unit := (* Appends a log entry, having `num_topics` topics, to the evm logs. @@ -34,26 +36,42 @@ Definition log_n : M unit := The number of topics to be included in the log entry. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* topics := (* TODO expression *) in + 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 *) - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - let* log_entry := blocks.Log (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "log_entry" [[ + blocks.Log ~(| - |) in + |) in + ]] in (* TODO assignment *) - (* 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/memory.v b/coq/ethereum/frontier/vm/instructions/memory.v index 7c58fb1ea5..fdb712b2f6 100644 --- a/coq/ethereum/frontier/vm/instructions/memory.v +++ b/coq/ethereum/frontier/vm/instructions/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM Memory instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require frontier.vm.gas. -Require frontier.vm.memory. -Require frontier.vm.stack. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.memory. +Require ethereum.frontier.vm.stack. -Definition mstore : M unit := +Definition mstore (evm : Evm) : M unit := (* Stores a word to memory. This also expands the memory, if the memory is @@ -30,32 +32,44 @@ Definition mstore : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* memory.memory_write (| - evm.["memory"], - start_position, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mstore8 (evm : Evm) : M unit := (* Stores a byte to memory. This also expands the memory, if the memory is @@ -67,33 +81,47 @@ Definition mstore8 : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ (* TODO expression *) - |) in - do* memory.memory_write (| - evm.["memory"], - start_position, - normalized_bytes_value - |) in - (* TODO statement *) - + ]] 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 : M unit := +Definition mload (evm : Evm) : M unit := (* Load word from memory. @@ -103,35 +131,47 @@ Definition mload : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.memory_read_bytes (| - evm.["memory"], - start_position, - ethereum_types.numeric.U256 (| - (* 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 - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition msize : M unit := +Definition msize (evm : Evm) : M unit := (* Push the size of active memory in bytes onto the stack. @@ -142,17 +182,21 @@ Definition msize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["memory"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/frontier/vm/instructions/stack.v index b8ce6b4c9a..6c8cd9cef5 100644 --- a/coq/ethereum/frontier/vm/instructions/stack.v +++ b/coq/ethereum/frontier/vm/instructions/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM stack related instructions. Require functools. Require ethereum_types.numeric. -Require frontier.vm.exceptions. -Require frontier.vm.gas. -Require frontier.vm.memory. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.exceptions. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.memory. -Definition pop : M unit := +Definition pop (evm : Evm) : M unit := (* Remove item from stack. @@ -28,18 +30,22 @@ Definition pop : M unit := The current EVM frame. *) - do* stack.["pop"] (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in + |) ]] in (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition push_n : M unit := +Definition push_n (evm : Evm) (num_bytes : int) : M unit := (* Pushes a N-byte immediate onto the stack. @@ -54,29 +60,33 @@ Definition push_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - evm.["code"], - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - num_bytes + |) ]] 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 - do* stack.["push"] (| - evm.["stack"], - data_to_push - |) in - (* TODO statement *) - - -Definition dup_n : M unit := + |) 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. @@ -91,20 +101,26 @@ Definition dup_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - let* data_to_duplicate := (* TODO expression *) in - do* stack.["push"] (| - evm.["stack"], - data_to_duplicate - |) 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 : M unit := +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. @@ -123,11 +139,15 @@ Definition swap_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - (* 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/storage.v b/coq/ethereum/frontier/vm/instructions/storage.v index 111dc857a4..b9763cbd32 100644 --- a/coq/ethereum/frontier/vm/instructions/storage.v +++ b/coq/ethereum/frontier/vm/instructions/storage.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Storage Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM storage related instructions. *) Require ethereum_types.numeric. -Require frontier.state. -Require frontier.vm.gas. -Require frontier.vm.stack. +Require ethereum.frontier.state. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.stack. -Definition sload : M unit := +Definition sload (evm : Evm) : M unit := (* Loads to the stack, the value corresponding to a certain key from the storage of the current account. @@ -28,28 +30,36 @@ Definition sload : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_SLOAD - |) in - let* value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sstore (evm : Evm) : M unit := (* Stores a value at a certain key in the current context's storage. @@ -59,30 +69,40 @@ Definition sstore : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in - let* current_value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in + |) 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - do* state.set_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key, - new_value - |) in - (* TODO statement *) - + 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.v b/coq/ethereum/frontier/vm/instructions/system.v index 063c8888b8..d3eb2606a2 100644 --- a/coq/ethereum/frontier/vm/instructions/system.v +++ b/coq/ethereum/frontier/vm/instructions/system.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) System Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,14 +15,15 @@ Implementations of the EVM system related instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require frontier.fork_types. -Require frontier.state. -Require frontier.utils.address. -Require frontier.vm.gas. -Require frontier.vm.memory. -Require frontier.vm.stack. +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 : M unit := +Definition create (evm : Evm) : M unit := (* Creates a new account with associated code. @@ -31,43 +33,65 @@ Definition create : M unit := The current EVM frame. *) (* TODO statement *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - let* create_message_gas := evm.["gas_left"] in + |) ]] 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 *) - let* sender_address := evm.["message"].["current_target"] in - let* sender := state.get_account (| - evm.["env"].["state"], - sender_address - |) in - let* contract_address := utils.address.compute_contract_address (| - evm.["message"].["current_target"], - state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["nonce"] - |) in - (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition return_ : M unit := +Definition return_ (evm : Evm) : M unit := (* Halts execution returning output data. @@ -76,65 +100,83 @@ Definition return_ : M unit := evm : The current EVM frame. *) - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) + |) ]] 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 : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_input_start_position, - memory_input_size - |) in - let* code := state.get_account (| - evm.["env"].["state"], - code_address - |).["code"] in - let* child_message := Message (| + 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 - let* child_evm := process_message (| - child_message, - evm.["env"] - |) in + |) 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 *) - let* actual_output_size := min (| - memory_output_size, - ethereum_types.numeric.U256 (| - len (| - child_evm.["output"] + 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 - do* memory.memory_write (| - evm.["memory"], + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), memory_output_start_position, (* TODO expression *) - |) in + |) ]] in + M.pure tt. - -Definition call : M unit := +Definition call (evm : Evm) : M unit := (* Message-call into an account. @@ -143,55 +185,81 @@ Definition call : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* message_call_gas := gas.calculate_message_call_gas (| - evm.["env"].["state"], - gas, - to, - value - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition callcode (evm : Evm) : M unit := (* Message-call into this account with alternative account’s code. @@ -200,56 +268,84 @@ Definition callcode : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* to := evm.["message"].["current_target"] in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* message_call_gas := gas.calculate_message_call_gas (| - evm.["env"].["state"], - gas, - to, - value - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition selfdestruct (evm : Evm) : M unit := (* Halt execution and register account for later deletion. @@ -258,44 +354,58 @@ Definition selfdestruct : M unit := evm : The current EVM frame. *) - let* beneficiary := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* gas_cost := gas.GAS_ZERO in - let* originator := evm.["message"].["current_target"] in - let* refunded_accounts := evm.["accounts_to_delete"] in - let* parent_evm := evm.["message"].["parent_evm"] in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - let* beneficiary_balance := state.get_account (| - evm.["env"].["state"], - beneficiary - |).["balance"] in - let* originator_balance := state.get_account (| - evm.["env"].["state"], - originator - |).["balance"] in - do* state.set_account_balance (| - evm.["env"].["state"], - beneficiary, + 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 (| - evm.["env"].["state"], - originator, - ethereum_types.numeric.U256 (| - (* 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* evm.["accounts_to_delete"].["add"] (| - originator - |) in + |) ]] 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.v b/coq/ethereum/frontier/vm/interpreter.v index 5cc08cb04f..3464c3e511 100644 --- a/coq/ethereum/frontier/vm/interpreter.v +++ b/coq/ethereum/frontier/vm/interpreter.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Interpreter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +18,18 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.trace. -Require frontier.blocks. -Require frontier.fork_types. -Require frontier.state. -Require frontier.vm. -Require frontier.vm.gas. -Require frontier.vm.precompiled_contracts.mapping. -Require frontier.vm.exceptions. -Require frontier.vm.instructions. -Require frontier.vm.runtime. - -Definition process_message_call : M unit := +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`. @@ -47,19 +49,21 @@ Definition process_message_call : M unit := *) (* TODO statement *) (* TODO statement *) - let* tx_end := ethereum.trace.TransactionEnd (| - (* TODO expression *), - evm.["output"], - evm.["error"] - |) in - do* ethereum.trace.evm_trace (| - evm, - tx_end - |) in + 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 : M unit := +Definition process_create_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -75,22 +79,24 @@ Definition process_create_message : M unit := evm: :py:class:`~ethereum.frontier.vm.Evm` Items containing execution specific objects. *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.destroy_storage (| - env.["state"], - message.["current_target"] - |) in - let* evm := process_message (| - message, - env - |) in + 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 : M unit := +Definition process_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -107,23 +113,25 @@ Definition process_message : M unit := Items containing execution specific objects *) (* TODO statement *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.touch_account (| - env.["state"], - message.["current_target"] - |) in + 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 *) - let* evm := execute_code (| - message, - env - |) in + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition execute_code : M unit := +Definition execute_code (message : Message) (env : Environment) : M Evm := (* Executes bytecode present in the `message`. @@ -139,13 +147,19 @@ Definition execute_code : M unit := evm: `ethereum.vm.EVM` Items containing execution specific objects *) - let* code := message.["code"] in - let* valid_jump_destinations := runtime.get_valid_jump_destinations (| - code - |) in - let* evm := Evm (| - - |) in + 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.v b/coq/ethereum/frontier/vm/memory.v index 94b6a44639..88b516318f 100644 --- a/coq/ethereum/frontier/vm/memory.v +++ b/coq/ethereum/frontier/vm/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.byte. -Definition memory_write : M unit := +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := (* Writes to memory. @@ -30,9 +31,9 @@ Definition memory_write : M unit := Data to write to memory. *) (* TODO assignment *) + M.pure tt. - -Definition memory_read_bytes : M unit := +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := (* Read bytes from memory. @@ -51,9 +52,9 @@ Definition memory_read_bytes : M unit := Data read from memory. *) (* TODO statement *) + M.pure tt. - -Definition buffer_read : M unit := +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := (* Read bytes from a buffer. Padding with zeros if necessary. @@ -72,4 +73,4 @@ Definition buffer_read : M unit := Data read from memory. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/frontier/vm/precompiled_contracts/__init__.v b/coq/ethereum/frontier/vm/precompiled_contracts/__init__.v index c38b032f9f..b96bd9e8b1 100644 --- a/coq/ethereum/frontier/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/frontier/vm/precompiled_contracts/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,4 +14,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require frontier.utils.hexadecimal. +Require ethereum.frontier.utils.hexadecimal. diff --git a/coq/ethereum/frontier/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/frontier/vm/precompiled_contracts/ecrecover.v index 818e3fd02c..d210f88bdb 100644 --- a/coq/ethereum/frontier/vm/precompiled_contracts/ecrecover.v +++ b/coq/ethereum/frontier/vm/precompiled_contracts/ecrecover.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,11 +17,11 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require frontier.vm. -Require frontier.vm.gas. -Require frontier.vm.memory. +Require ethereum.frontier.vm. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.memory. -Definition ecrecover : M unit := +Definition ecrecover (evm : Evm) : M unit := (* Decrypts the address using elliptic curve DSA recovery mechanism and writes the address to output. @@ -30,64 +31,80 @@ Definition ecrecover : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* message_hash_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* message_hash := ethereum.crypto.hash.Hash32 (| - message_hash_bytes - |) in - let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + ethereum_types.numeric.U256 ~(| + 32 |) - |) - |) in - let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 + ]] 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 *) - let* address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/frontier/vm/precompiled_contracts/identity.v index 2707859a47..84c32782d5 100644 --- a/coq/ethereum/frontier/vm/precompiled_contracts/identity.v +++ b/coq/ethereum/frontier/vm/precompiled_contracts/identity.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,10 @@ Implementation of the `IDENTITY` precompiled contract. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require frontier.vm. -Require frontier.vm.gas. +Require ethereum.frontier.vm. +Require ethereum.frontier.vm.gas. -Definition identity : M unit := +Definition identity (evm : Evm) : M unit := (* Writes the message data to output. @@ -26,11 +27,15 @@ Definition identity : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/frontier/vm/precompiled_contracts/mapping.v b/coq/ethereum/frontier/vm/precompiled_contracts/mapping.v index b7c905d8d5..4b4e1ee90b 100644 --- a/coq/ethereum/frontier/vm/precompiled_contracts/mapping.v +++ b/coq/ethereum/frontier/vm/precompiled_contracts/mapping.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,8 +14,9 @@ Mapping of precompiled contracts their implementations. *) Require typing. -Require frontier.fork_types. -Require frontier.vm.precompiled_contracts.ecrecover. -Require frontier.vm.precompiled_contracts.identity. -Require frontier.vm.precompiled_contracts.ripemd160. -Require frontier.vm.precompiled_contracts.sha256. +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.v b/coq/ethereum/frontier/vm/precompiled_contracts/ripemd160.v index bc5e73dd3c..fe2c66bbe6 100644 --- a/coq/ethereum/frontier/vm/precompiled_contracts/ripemd160.v +++ b/coq/ethereum/frontier/vm/precompiled_contracts/ripemd160.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `RIPEMD160` precompiled contract. *) -Definition ripemd160 : M unit := +Definition ripemd160 (evm : Evm) : M unit := (* Writes the ripemd160 hash to output. @@ -22,21 +23,29 @@ Definition ripemd160 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 - let* hash_bytes := hashlib.["new"] (| - (* TODO expression *), - data - |).["digest"] (| - - |) in - let* padded_hash := left_pad_zero_bytes (| - hash_bytes, - (* TODO expression *) - |) in + |) ]] 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.v b/coq/ethereum/frontier/vm/precompiled_contracts/sha256.v index da6972d411..3ba3ffe7aa 100644 --- a/coq/ethereum/frontier/vm/precompiled_contracts/sha256.v +++ b/coq/ethereum/frontier/vm/precompiled_contracts/sha256.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `SHA256` precompiled contract. *) -Definition sha256 : M unit := +Definition sha256 (evm : Evm) : M unit := (* Writes the sha256 hash to output. @@ -22,11 +23,15 @@ Definition sha256 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/frontier/vm/runtime.v b/coq/ethereum/frontier/vm/runtime.v index ea2f476cdf..779eae3568 100644 --- a/coq/ethereum/frontier/vm/runtime.v +++ b/coq/ethereum/frontier/vm/runtime.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Runtime Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Runtime related operations used while executing EVM code. Require typing. Require ethereum_types.numeric. -Require frontier.vm.instructions. +Require ethereum.frontier.vm.instructions. -Definition get_valid_jump_destinations : M unit := +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := (* Analyze the evm code to obtain the set of valid jump destinations. @@ -38,12 +39,16 @@ Definition get_valid_jump_destinations : M unit := valid_jump_destinations: `Set[Uint]` The set of valid jump destinations in the code. *) - let* valid_jump_destinations := set (| - - |) in - let* pc := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/frontier/vm/stack.v index ff1804132f..be1ae63575 100644 --- a/coq/ethereum/frontier/vm/stack.v +++ b/coq/ethereum/frontier/vm/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Implementation of the stack operators for the EVM. Require typing. Require ethereum_types.numeric. -Require frontier.vm.exceptions. +Require ethereum.frontier.vm.exceptions. -Definition pop : M unit := +Definition pop (stack : (* TODO type *)) : M U256 := (* Pops the top item off of `stack`. @@ -33,9 +34,9 @@ Definition pop : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition push : M unit := +Definition push (stack : (* TODO type *)) (value : U256) : M unit := (* Pushes `value` onto `stack`. @@ -50,4 +51,4 @@ Definition push : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/genesis.v b/coq/ethereum/genesis.v index e7cc348c08..87553b04e5 100644 --- a/coq/ethereum/genesis.v +++ b/coq/ethereum/genesis.v @@ -1,3 +1,4 @@ +(* Generated *) (* Types and functions for beginning a new chain. @@ -14,34 +15,40 @@ The genesis configuration for a chain is specified with a *) -Definition get_genesis_configuration : M unit := +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. *) - let* genesis_path := (* TODO expression *) in - let* genesis_bytes := pkgutil.["get_data"] (| - (* TODO expression *), - genesis_path - |) in + 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 *) - let* genesis_data := json.["loads"] (| - genesis_bytes.["decode"] (| + do* M.assign "genesis_data" [[ + M.get_field ~(| M.get_local ~(| "json" |), "loads" |) ~(| + M.get_field ~(| M.get_local ~(| "genesis_bytes" |), "decode" |) ~(| - |) - |) in + |) + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition hex_or_base_10_str_to_u256 : M unit := +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 : M unit := +Definition add_genesis_block (hardfork : (* TODO type *)) (chain : Any) (genesis : GenesisConfiguration) : M unit := (* Adds the genesis block to an empty blockchain. @@ -82,23 +89,31 @@ Definition add_genesis_block : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* fields := (* TODO expression *) in + do* M.assign "fields" [[ + (* TODO expression *) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* genesis_header := hardfork.["Header"] (| - - |) in - let* block_fields := (* TODO expression *) in + do* M.assign "genesis_header" [[ + M.get_field ~(| hardfork, "Header" |) ~(| + + |) in + ]] in + do* M.assign "block_fields" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* genesis_block := hardfork.["Block"] (| - - |) in - do* chain.["blocks"].["append"] (| - genesis_block - |) in + 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__.v b/coq/ethereum/gray_glacier/__init__.v index 5e262a1a7b..42f5c355fb 100644 --- a/coq/ethereum/gray_glacier/__init__.v +++ b/coq/ethereum/gray_glacier/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* The Gray Glacier fork delays the difficulty bomb. There are no other changes in this fork. diff --git a/coq/ethereum/gray_glacier/blocks.v b/coq/ethereum/gray_glacier/blocks.v index e159b28889..c51b2bf575 100644 --- a/coq/ethereum/gray_glacier/blocks.v +++ b/coq/ethereum/gray_glacier/blocks.v @@ -1,3 +1,4 @@ +(* 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 @@ -14,6 +15,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. -Require gray_glacier.fork_types. -Require gray_glacier.transactions. +Require ethereum.crypto.hash. +Require ethereum.gray_glacier.fork_types. +Require ethereum.gray_glacier.transactions. diff --git a/coq/ethereum/gray_glacier/bloom.v b/coq/ethereum/gray_glacier/bloom.v index 43fd209ef4..1c35fb218b 100644 --- a/coq/ethereum/gray_glacier/bloom.v +++ b/coq/ethereum/gray_glacier/bloom.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Logs Bloom ^^^^^^^^^^^^^^^^^^^ @@ -19,10 +20,10 @@ eliminating blocks and receipts from their search. Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require gray_glacier.blocks. -Require gray_glacier.fork_types. +Require ethereum.gray_glacier.blocks. +Require ethereum.gray_glacier.fork_types. -Definition add_to_bloom : M unit := +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := (* Add a bloom entry to the bloom filter (`bloom`). @@ -37,13 +38,15 @@ Definition add_to_bloom : M unit := bloom_entry : An entry which is to be added to bloom filter. *) - let* hash := ethereum.crypto.hash.keccak256 (| - bloom_entry - |) in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition logs_bloom : M unit := +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := (* Obtain the logs bloom from a list of log entries. @@ -63,4 +66,4 @@ Definition logs_bloom : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/gray_glacier/exceptions.v b/coq/ethereum/gray_glacier/exceptions.v index 137ea143f6..9a313f6d0e 100644 --- a/coq/ethereum/gray_glacier/exceptions.v +++ b/coq/ethereum/gray_glacier/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Exceptions specific to this fork. *) diff --git a/coq/ethereum/gray_glacier/fork.v b/coq/ethereum/gray_glacier/fork.v index 3ce1f80cf7..37cba61d8e 100644 --- a/coq/ethereum/gray_glacier/fork.v +++ b/coq/ethereum/gray_glacier/fork.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^ @@ -20,16 +21,18 @@ Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.ethash. Require ethereum.exceptions. -Require gray_glacier.blocks. -Require gray_glacier.bloom. -Require gray_glacier.fork_types. -Require gray_glacier.state. -Require gray_glacier.transactions. -Require gray_glacier.trie. -Require gray_glacier.utils.message. -Require gray_glacier.vm.interpreter. - -Definition apply_fork : M unit := +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. @@ -49,9 +52,9 @@ Definition apply_fork : M unit := Upgraded block chain object for this hard fork. *) (* TODO statement *) + M.pure tt. - -Definition get_last_256_block_hashes : M unit := +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. @@ -71,22 +74,28 @@ Definition get_last_256_block_hashes : M unit := recent_block_hashes : `List[Hash32]` Hashes of the recent 256 blocks in order of increasing block number. *) - let* recent_blocks := (* TODO expression *) in - (* TODO statement *) - let* recent_block_hashes := (* TODO expression *) in - (* TODO statement *) - let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *).["header"] - |) - |) in - do* recent_block_hashes.["append"] (| - most_recent_block_hash - |) in - (* TODO statement *) - - -Definition state_transition : M unit := + 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. @@ -108,43 +117,47 @@ Definition state_transition : M unit := block : Block to apply to `chain`. *) - let* parent_header := (* TODO expression *).["header"] in - do* validate_header (| - block.["header"], - parent_header - |) in - do* validate_ommers (| - block.["ommers"], - block.["header"], + 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 - let* apply_body_output := apply_body (| - chain.["state"], - get_last_256_block_hashes (| - chain - |), - block.["header"].["coinbase"], - block.["header"].["number"], - block.["header"].["base_fee_per_gas"], - block.["header"].["gas_limit"], - block.["header"].["timestamp"], - block.["header"].["difficulty"], - block.["transactions"], - block.["ommers"], - chain.["chain_id"] - |) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - do* chain.["blocks"].["append"] (| + |) ]] 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 + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_base_fee_per_gas : M unit := +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. @@ -164,13 +177,15 @@ Definition calculate_base_fee_per_gas : M unit := base_fee_per_gas : `Uint` Base fee per gas for the block. *) - let* parent_gas_target := (* TODO expression *) in + do* M.assign "parent_gas_target" [[ + (* TODO expression *) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition validate_header : M unit := +Definition validate_header (header : Header) (parent_header : Header) : M unit := (* Verifies a block header. @@ -189,37 +204,45 @@ Definition validate_header : M unit := Parent Header of the header to check for correctness *) (* TODO statement *) - let* expected_base_fee_per_gas := calculate_base_fee_per_gas (| - header.["gas_limit"], - parent_header.["gas_limit"], - parent_header.["gas_used"], - parent_header.["base_fee_per_gas"] - |) in - (* TODO statement *) - let* parent_has_ommers := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* block_difficulty := calculate_block_difficulty (| - header.["number"], - header.["timestamp"], - parent_header.["timestamp"], - parent_header.["difficulty"], - parent_has_ommers - |) in - (* TODO statement *) - let* block_parent_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - parent_header - |) - |) in - (* TODO statement *) - do* validate_proof_of_work (| + 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 - + |) ]] in + M.pure tt. -Definition generate_header_hash_for_pow : M unit := +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. @@ -242,11 +265,13 @@ Definition generate_header_hash_for_pow : M unit := hash : `Hash32` The PoW valid rlp hash of the passed in header. *) - let* header_data_without_pow_artefacts := (* TODO expression *) in + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition validate_proof_of_work : M unit := +Definition validate_proof_of_work (header : Header) : M unit := (* Validates the Proof of Work constraints. @@ -261,19 +286,25 @@ Definition validate_proof_of_work : M unit := header : Header of interest. *) - let* header_hash := generate_header_hash_for_pow (| - header - |) in - let* cache := ethereum.ethash.generate_cache (| - header.["number"] - |) in + 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 *) - let* limit := (* TODO expression *) in + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition check_transaction : M unit := +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. @@ -301,15 +332,17 @@ Definition check_transaction : M unit := If the transaction is not includable. *) (* TODO statement *) - let* sender_address := recover_sender (| - chain_id, - tx - |) in + 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 : M unit := +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. @@ -330,13 +363,15 @@ Definition make_receipt : M unit := receipt : The receipt for the transaction. *) - let* receipt := blocks.Receipt (| + do* M.assign "receipt" [[ + blocks.Receipt ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition apply_body : M unit := +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. @@ -379,25 +414,31 @@ Definition apply_body : M unit := apply_body_output : `ApplyBodyOutput` Output of applying the block body to the state. *) - let* gas_available := block_gas_limit in + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - do* pay_rewards (| + do* [[ M.get_local ~(| "pay_rewards" |) ~(| state, block_number, coinbase, ommers - |) in - let* block_gas_used := (* TODO expression *) in - let* block_logs_bloom := bloom.logs_bloom (| - block_logs - |) in - (* TODO statement *) - - -Definition validate_ommers : M unit := + |) ]] 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. @@ -419,23 +460,31 @@ Definition validate_ommers : M unit := chain : History and current state. *) - let* block_hash := rlp.["rlp_hash"] (| - block_header - |) in + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* ommers_hashes := (* TODO expression *) in + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* recent_canonical_blocks := (* TODO expression *) in - let* recent_canonical_block_hashes := (* TODO expression *) in + 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 : M unit := +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. @@ -461,21 +510,25 @@ Definition pay_rewards : M unit := ommers : List of ommers mentioned in the current block. *) - let* ommer_count := ethereum_types.numeric.U256 (| - len (| - ommers - |) - |) in - let* miner_reward := (* TODO expression *) in - do* state.create_ether (| + 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, - miner_reward - |) in + M.get_local ~(| "miner_reward" |) + |) ]] in (* TODO statement *) + M.pure tt. - -Definition process_transaction : M unit := +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := (* Execute a transaction against the provided environment. @@ -503,74 +556,108 @@ Definition process_transaction : M unit := Logs generated during execution. *) (* TODO statement *) - let* sender := env.["origin"] in - let* sender_account := state.get_account (| - env.["state"], - sender - |) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* effective_gas_fee := (* TODO expression *) in - let* gas := (* TODO expression *) in - do* state.increment_nonce (| - env.["state"], - sender - |) in - let* sender_balance_after_gas_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - ethereum_types.numeric.U256 (| - sender_balance_after_gas_fee + 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 - let* preaccessed_addresses := set (| - - |) in - let* preaccessed_storage_keys := set (| - - |) in - (* TODO statement *) - let* message := utils.message.prepare_message (| - sender, - tx.["to"], - tx.["value"], - tx.["data"], - gas, - env - |) in - let* output := vm.interpreter.process_message_call (| - message, - env - |) in - let* gas_used := (* TODO expression *) in - let* gas_refund := min (| - (* TODO expression *), - ethereum_types.numeric.Uint (| - output.["refund_counter"] - |) - |) in - let* gas_refund_amount := (* TODO expression *) in - let* priority_fee_per_gas := (* TODO expression *) in - let* transaction_fee := (* TODO expression *) in - let* total_gas_used := (* TODO expression *) in - let* sender_balance_after_refund := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - sender_balance_after_refund - |) in - let* coinbase_balance_after_mining_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - - -Definition validate_transaction : M unit := + |) ]] 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. @@ -598,9 +685,9 @@ Definition validate_transaction : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition calculate_intrinsic_cost : M unit := +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := (* Calculates the gas that is charged before execution is started. @@ -623,15 +710,19 @@ Definition calculate_intrinsic_cost : M unit := verified : `ethereum.base_types.Uint` The intrinsic cost of the transaction. *) - let* data_cost := (* TODO expression *) in + do* M.assign "data_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) - let* access_list_cost := (* TODO expression *) in + do* M.assign "access_list_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition recover_sender : M unit := +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := (* Extracts the sender address from a transaction. @@ -658,9 +749,9 @@ Definition recover_sender : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_pre155 : M unit := +Definition signing_hash_pre155 (tx : LegacyTransaction) : M Hash32 := (* Compute the hash of a transaction used in a legacy (pre EIP 155) signature. @@ -675,9 +766,9 @@ Definition signing_hash_pre155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_155 : M unit := +Definition signing_hash_155 (tx : LegacyTransaction) (chain_id : U64) : M Hash32 := (* Compute the hash of a transaction used in a EIP 155 signature. @@ -694,9 +785,9 @@ Definition signing_hash_155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_2930 : M unit := +Definition signing_hash_2930 (tx : AccessListTransaction) : M Hash32 := (* Compute the hash of a transaction used in a EIP 2930 signature. @@ -711,9 +802,9 @@ Definition signing_hash_2930 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_1559 : M unit := +Definition signing_hash_1559 (tx : FeeMarketTransaction) : M Hash32 := (* Compute the hash of a transaction used in a EIP 1559 signature. @@ -728,9 +819,9 @@ Definition signing_hash_1559 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition compute_header_hash : M unit := +Definition compute_header_hash (header : Header) : M Hash32 := (* Computes the hash of a block header. @@ -763,9 +854,9 @@ Definition compute_header_hash : M unit := Hash of the header. *) (* TODO statement *) + M.pure tt. - -Definition check_gas_limit : M unit := +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := (* Validates the gas limit for a block. @@ -793,14 +884,16 @@ Definition check_gas_limit : M unit := check : `bool` True if gas limit constraints are satisfied, False otherwise. *) - let* max_adjustment_delta := (* TODO expression *) in + 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 : M unit := +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. @@ -839,9 +932,15 @@ Definition calculate_block_difficulty : M unit := difficulty : `ethereum.base_types.Uint` Computed difficulty for a block. *) - let* offset := (* TODO expression *) in - let* difficulty := (* TODO expression *) in - let* num_bomb_periods := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - + 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.v b/coq/ethereum/gray_glacier/fork_types.v index 14de99d5e5..d84cffdf45 100644 --- a/coq/ethereum/gray_glacier/fork_types.v +++ b/coq/ethereum/gray_glacier/fork_types.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Types ^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. +Require ethereum.__init__. +Require ethereum.crypto.hash. -Definition encode_account : M unit := +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := (* Encode `Account` dataclass. @@ -26,4 +28,4 @@ Definition encode_account : M unit := encoded without providing a storage root. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/gray_glacier/state.v b/coq/ethereum/gray_glacier/state.v index dba869a9be..854221db7c 100644 --- a/coq/ethereum/gray_glacier/state.v +++ b/coq/ethereum/gray_glacier/state.v @@ -1,3 +1,4 @@ +(* Generated *) (* State ^^^^^ @@ -22,10 +23,10 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require gray_glacier.fork_types. -Require gray_glacier.trie. +Require ethereum.gray_glacier.fork_types. +Require ethereum.gray_glacier.trie. -Definition close_state : M unit := +Definition close_state (state : State) : M unit := (* Free resources held by the state. Used by optimized implementations to release file descriptors. @@ -34,9 +35,9 @@ Definition close_state : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition begin_transaction : M unit := +Definition begin_transaction (state : State) : M unit := (* Start a state transaction. @@ -48,12 +49,12 @@ Definition begin_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition commit_transaction : M unit := +Definition commit_transaction (state : State) : M unit := (* Commit a state transaction. @@ -62,13 +63,13 @@ Definition commit_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["pop"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition rollback_transaction : M unit := +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. @@ -80,9 +81,9 @@ Definition rollback_transaction : M unit := *) (* TODO assignment *) (* TODO statement *) + M.pure tt. - -Definition get_account : M unit := +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. @@ -102,14 +103,16 @@ Definition get_account : M unit := account : `Account` Account at address. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition get_account_optional : M unit := +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. @@ -126,14 +129,16 @@ Definition get_account_optional : M unit := account : `Account` Account at address. *) - let* account := trie.trie_get (| - state.["_main_trie"], - address - |) in + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition set_account : M unit := +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()`). @@ -147,14 +152,14 @@ Definition set_account : M unit := account : `Account` Account to set at address. *) - do* trie.trie_set (| - state.["_main_trie"], + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), address, account - |) in + |) ]] in + M.pure tt. - -Definition destroy_account : M unit := +Definition destroy_account (state : State) (address : Address) : M unit := (* Completely remove the account at `address` and all of its storage. @@ -169,18 +174,18 @@ Definition destroy_account : M unit := address : `Address` Address of account to destroy. *) - do* destroy_storage (| + do* [[ M.get_local ~(| "destroy_storage" |) ~(| state, address - |) in - do* set_account (| + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - (* TODO expression *) - |) in + tt + |) ]] in + M.pure tt. - -Definition destroy_storage : M unit := +Definition destroy_storage (state : State) (address : Address) : M unit := (* Completely remove the storage at `address`. @@ -192,9 +197,9 @@ Definition destroy_storage : M unit := Address of account whose storage is to be deleted. *) (* TODO statement *) + M.pure tt. - -Definition mark_account_created : M unit := +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 @@ -211,12 +216,12 @@ Definition mark_account_created : M unit := address : `Address` Address of the account that has been created. *) - do* state.["created_accounts"].["add"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| address - |) in - + |) ]] in + M.pure tt. -Definition get_storage : M unit := +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. @@ -235,19 +240,23 @@ Definition get_storage : M unit := value : `U256` Value at the key. *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition set_storage : M unit := +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. @@ -264,19 +273,21 @@ Definition set_storage : M unit := Value to set at the key. *) (* TODO statement *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - do* trie.trie_set (| - trie, + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), key, value - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition storage_root : M unit := +Definition storage_root (state : State) (address : Address) : M Root := (* Calculate the storage root of an account. @@ -294,9 +305,9 @@ Definition storage_root : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition state_root : M unit := +Definition state_root (state : State) : M Root := (* Calculate the state root. @@ -313,9 +324,9 @@ Definition state_root : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition account_exists : M unit := +Definition account_exists (state : State) (address : Address) : M bool := (* Checks if an account exists in the state trie @@ -332,9 +343,9 @@ Definition account_exists : M unit := True if account exists in the state trie, False otherwise *) (* TODO statement *) + M.pure tt. - -Definition account_has_code_or_nonce : M unit := +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := (* Checks if an account has non zero nonce or non empty code @@ -351,14 +362,16 @@ Definition account_has_code_or_nonce : M unit := True if if an account has non zero nonce or non empty code, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_empty : M unit := +Definition is_account_empty (state : State) (address : Address) : M bool := (* Checks if an account has zero nonce, empty code and zero balance. @@ -375,14 +388,16 @@ Definition is_account_empty : M unit := True if if an account has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition account_exists_and_is_empty : M unit := +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. @@ -400,14 +415,16 @@ Definition account_exists_and_is_empty : M unit := True if an account exists and has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_alive : M unit := +Definition is_account_alive (state : State) (address : Address) : M bool := (* Check whether is an account is both in the state and non empty. @@ -423,49 +440,51 @@ Definition is_account_alive : M unit := is_alive : `bool` True if the account is alive. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition modify_state : M unit := +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := (* Modify an `Account` in the `State`. *) - do* set_account (| + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - ethereum_types.frozen.modify (| - get_account (| + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| state, address |), f |) - |) in - + |) ]] in + M.pure tt. -Definition move_ether : M unit := +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := (* Move funds between accounts. *) (* TODO statement *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, sender_address, - reduce_sender_balance - |) in - do* modify_state (| + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| state, recipient_address, - increase_recipient_balance - |) in - + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. -Definition set_account_balance : M unit := +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := (* Sets the balance of an account. @@ -481,14 +500,14 @@ Definition set_account_balance : M unit := The amount that needs to set in balance. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - set_balance - |) in + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. - -Definition touch_account : M unit := +Definition touch_account (state : State) (address : Address) : M unit := (* Initializes an account to state. @@ -501,9 +520,9 @@ Definition touch_account : M unit := The address of the account that need to initialised. *) (* TODO statement *) + M.pure tt. - -Definition increment_nonce : M unit := +Definition increment_nonce (state : State) (address : Address) : M unit := (* Increments the nonce of an account. @@ -516,14 +535,14 @@ Definition increment_nonce : M unit := Address of the account whose nonce needs to be incremented. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_nonce - |) in + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. - -Definition set_code : M unit := +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := (* Sets Account code. @@ -539,14 +558,14 @@ Definition set_code : M unit := The bytecode that needs to be set. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - write_code - |) in - + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. -Definition create_ether : M unit := +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := (* Add newly created ether to an account. @@ -560,14 +579,14 @@ Definition create_ether : M unit := The amount of ether to be added to the account of interest. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_balance - |) in - + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. -Definition get_storage_original : M unit := +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 @@ -584,10 +603,12 @@ Definition get_storage_original : M unit := *) (* TODO statement *) (* TODO assignment *) - let* original_account_trie := original_trie.["get"] (| - address - |) in + 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.v b/coq/ethereum/gray_glacier/transactions.v index 7b848450cc..3223df95d8 100644 --- a/coq/ethereum/gray_glacier/transactions.v +++ b/coq/ethereum/gray_glacier/transactions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, @@ -9,19 +10,20 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require gray_glacier.exceptions. -Require gray_glacier.fork_types. +Require ethereum.__init__. +Require ethereum.gray_glacier.exceptions. +Require ethereum.gray_glacier.fork_types. -Definition encode_transaction : M unit := +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 : M unit := +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.v b/coq/ethereum/gray_glacier/trie.v index 548de91e1c..6b8953f256 100644 --- a/coq/ethereum/gray_glacier/trie.v +++ b/coq/ethereum/gray_glacier/trie.v @@ -1,3 +1,4 @@ +(* Generated *) (* State Trie ^^^^^^^^^^ @@ -14,7 +15,7 @@ The state trie is the structure responsible for storing *) -Definition encode_internal_node : M unit := +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 @@ -35,22 +36,24 @@ Definition encode_internal_node : M unit := *) (* TODO statement *) (* TODO statement *) - let* encoded := rlp.["encode"] (| - unencoded - |) in + 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 : M unit := +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 : M unit := +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. @@ -66,9 +69,9 @@ Definition copy_trie : M unit := A copy of the trie. *) (* TODO statement *) + M.pure tt. - -Definition trie_set : M unit := +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := (* Stores an item in a Merkle Trie. @@ -85,9 +88,9 @@ Definition trie_set : M unit := Node to insert at `key`. *) (* TODO statement *) + M.pure tt. - -Definition trie_get : M unit := +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := (* Gets an item from the Merkle Trie. @@ -106,17 +109,17 @@ Definition trie_get : M unit := Node at `key` in the trie. *) (* TODO statement *) + M.pure tt. - -Definition common_prefix_length : M unit := +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 : M unit := +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := (* Compresses nibble-list into a standard byte array with a flag. @@ -150,14 +153,16 @@ Definition nibble_list_to_compact : M unit := compressed : `bytearray` Compact byte array. *) - let* compact := bytearray (| + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition bytes_to_nibble_list : M unit := +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := (* Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). @@ -171,14 +176,16 @@ Definition bytes_to_nibble_list : M unit := nibble_list : `Bytes` The `Bytes` in nibble-list format. *) - let* nibble_list := bytearray (| - (* TODO expression *) - |) in + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _prepare_trie : M unit := +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. @@ -199,9 +206,9 @@ Definition _prepare_trie : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition root : M unit := +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := (* Computes the root of a modified merkle patricia trie (MPT). @@ -219,22 +226,26 @@ Definition root : M unit := root : `.fork_types.Root` MPT root of the underlying key-value pairs. *) - let* obj := _prepare_trie (| - trie, - get_storage_root - |) in - let* root_node := encode_internal_node (| - patricialize (| - obj, - Uint (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) + M.pure tt. - -Definition patricialize : M unit := +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := (* Structural composition function. @@ -254,21 +265,29 @@ Definition patricialize : M unit := Root node of `obj`. *) (* TODO statement *) - let* arbitrary_key := next (| - iter (| - obj - |) - |) in + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in (* TODO statement *) - let* substring := (* TODO expression *) in - let* prefix_length := len (| - substring - |) in + 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 *) - let* value := (* TODO expression *) in + do* M.assign "value" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/gray_glacier/utils/__init__.v b/coq/ethereum/gray_glacier/utils/__init__.v index beff4482b1..7f30fe939b 100644 --- a/coq/ethereum/gray_glacier/utils/__init__.v +++ b/coq/ethereum/gray_glacier/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions unique to this particular fork. *) diff --git a/coq/ethereum/gray_glacier/utils/address.v b/coq/ethereum/gray_glacier/utils/address.v index d40ce2219c..fbc8732917 100644 --- a/coq/ethereum/gray_glacier/utils/address.v +++ b/coq/ethereum/gray_glacier/utils/address.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,9 +19,10 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require gray_glacier.fork_types. +Require ethereum.__init__. +Require ethereum.gray_glacier.fork_types. -Definition to_address : M unit := +Definition to_address (data : (* TODO type *)) : M Address := (* Convert a Uint or U256 value to a valid address (20 bytes). @@ -35,9 +37,9 @@ Definition to_address : M unit := The obtained address. *) (* TODO statement *) + M.pure tt. - -Definition compute_contract_address : M unit := +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := (* Computes address of the new account that needs to be created. @@ -54,20 +56,26 @@ Definition compute_contract_address : M unit := address: `Address` The computed address of the new account. *) - let* computed_address := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *) - |) - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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 : M unit := +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. @@ -86,14 +94,22 @@ Definition compute_create2_contract_address : M unit := address: `ethereum.gray_glacier.fork_types.Address` The computed address of the new account. *) - let* preimage := (* TODO expression *) in - let* computed_address := ethereum.crypto.hash.keccak256 (| - preimage - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/gray_glacier/utils/hexadecimal.v index 1f3005468c..8de558f56b 100644 --- a/coq/ethereum/gray_glacier/utils/hexadecimal.v +++ b/coq/ethereum/gray_glacier/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Gray Glacier types. *) Require ethereum.utils.hexadecimal. -Require gray_glacier.fork_types. +Require ethereum.gray_glacier.fork_types. -Definition hex_to_root : M unit := +Definition hex_to_root (hex_string : str) : M Root := (* Convert hex string to trie root. @@ -31,9 +32,9 @@ Definition hex_to_root : M unit := Trie root obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bloom : M unit := +Definition hex_to_bloom (hex_string : str) : M Bloom := (* Convert hex string to bloom. @@ -48,9 +49,9 @@ Definition hex_to_bloom : M unit := Bloom obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_address : M unit := +Definition hex_to_address (hex_string : str) : M Address := (* Convert hex string to Address (20 bytes). @@ -65,4 +66,4 @@ Definition hex_to_address : M unit := The address obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/gray_glacier/utils/message.v b/coq/ethereum/gray_glacier/utils/message.v index 6d16f08c28..0f4d824221 100644 --- a/coq/ethereum/gray_glacier/utils/message.v +++ b/coq/ethereum/gray_glacier/utils/message.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For The Message Data-structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,13 +17,13 @@ specification. Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require gray_glacier.fork_types. -Require gray_glacier.state. -Require gray_glacier.vm. -Require gray_glacier.vm.precompiled_contracts.mapping. -Require gray_glacier.utils.address. +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 : M unit := +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. @@ -61,22 +62,24 @@ Definition prepare_message : M unit := Items containing contract creation or message call specific data. *) (* TODO statement *) - let* accessed_addresses := set (| + do* M.assign "accessed_addresses" [[ + M.get_local ~(| "set" |) ~(| - |) in - do* accessed_addresses.["add"] (| - current_target - |) in - do* accessed_addresses.["add"] (| + |) 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* accessed_addresses.["update"] (| - vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS.["keys"] (| + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS, "keys" |) ~(| |) - |) in - do* accessed_addresses.["update"] (| + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| preaccessed_addresses - |) in + |) ]] in (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/__init__.v b/coq/ethereum/gray_glacier/vm/__init__.v index 5bce4bde9d..0c6b028c65 100644 --- a/coq/ethereum/gray_glacier/vm/__init__.v +++ b/coq/ethereum/gray_glacier/vm/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,12 +19,12 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require gray_glacier.blocks. -Require gray_glacier.fork_types. -Require gray_glacier.state. -Require gray_glacier.vm.precompiled_contracts. +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 : M unit := +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of a successful `child_evm` into the parent `evm`. @@ -34,25 +35,31 @@ Definition incorporate_child_on_success : M unit := 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 *) - (* TODO statement *) - (* TODO statement *) - do* evm.["accounts_to_delete"].["update"] (| - child_evm.["accounts_to_delete"] - |) in - do* evm.["touched_accounts"].["update"] (| - child_evm.["touched_accounts"] - |) in - (* TODO statement *) - do* evm.["accessed_addresses"].["update"] (| - child_evm.["accessed_addresses"] - |) in - do* evm.["accessed_storage_keys"].["update"] (| - child_evm.["accessed_storage_keys"] - |) in + 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 : M unit := +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. @@ -65,5 +72,7 @@ Definition incorporate_child_on_error : M unit := *) (* TODO statement *) (* 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.v b/coq/ethereum/gray_glacier/vm/exceptions.v index 1784494410..47e26555d5 100644 --- a/coq/ethereum/gray_glacier/vm/exceptions.v +++ b/coq/ethereum/gray_glacier/vm/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Exceptions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/gray_glacier/vm/gas.v b/coq/ethereum/gray_glacier/vm/gas.v index eaa619555b..ca889413c1 100644 --- a/coq/ethereum/gray_glacier/vm/gas.v +++ b/coq/ethereum/gray_glacier/vm/gas.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Gas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,9 +18,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.trace. Require ethereum.utils.numeric. -Require gray_glacier.vm.exceptions. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.exceptions. -Definition charge_gas : M unit := +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := (* Subtracts `amount` from `evm.gas_left`. @@ -31,18 +33,18 @@ Definition charge_gas : M unit := The amount of gas the current operation requires. *) - do* ethereum.trace.evm_trace (| + do* [[ ethereum.trace.evm_trace ~(| evm, - ethereum.trace.GasAndRefund (| - int (| + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| amount |) |) - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_memory_gas_cost : M unit := +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, @@ -58,14 +60,22 @@ Definition calculate_memory_gas_cost : M unit := total_gas_cost : `ethereum.base_types.Uint` The gas cost for storing data in memory. *) - let* size_in_words := (* TODO expression *) in - let* linear_cost := (* TODO expression *) in - let* quadratic_cost := (* TODO expression *) in - let* total_gas_cost := (* TODO expression *) in + 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 : M unit := +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := (* Calculates the gas amount to extend memory @@ -81,22 +91,28 @@ Definition calculate_gas_extend_memory : M unit := ------- extend_memory: `ExtendMemory` *) - let* size_to_extend := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* to_be_paid := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* current_size := ethereum_types.numeric.Uint (| - len (| - memory - |) - |) in + 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 : M unit := +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. @@ -122,18 +138,22 @@ Definition calculate_message_call_gas : M unit := ------- message_call_gas: `MessageCallGas` *) - let* call_stipend := (* TODO expression *) in + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* gas := min (| - gas, - max_message_call_gas (| - (* TODO expression *) - |) - |) in + 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 : M unit := +Definition max_message_call_gas (gas : Uint) : M Uint := (* Calculates the maximum gas that is allowed for making a message call @@ -148,4 +168,4 @@ Definition max_message_call_gas : M unit := The maximum gas allowed for making the message-call. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/instructions/__init__.v b/coq/ethereum/gray_glacier/vm/instructions/__init__.v index b36b1ebfef..cbd7e7e63a 100644 --- a/coq/ethereum/gray_glacier/vm/instructions/__init__.v +++ b/coq/ethereum/gray_glacier/vm/instructions/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* EVM Instruction Encoding (Opcodes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/gray_glacier/vm/instructions/arithmetic.v b/coq/ethereum/gray_glacier/vm/instructions/arithmetic.v index ac2876fdf3..18132d79ee 100644 --- a/coq/ethereum/gray_glacier/vm/instructions/arithmetic.v +++ b/coq/ethereum/gray_glacier/vm/instructions/arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,11 @@ Implementations of the EVM Arithmetic instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require gray_glacier.vm.gas. -Require gray_glacier.vm.stack. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.stack. -Definition add : M unit := +Definition add (evm : Evm) : M unit := (* Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -28,27 +30,37 @@ Definition add : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_add"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sub (evm : Evm) : M unit := (* Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -59,27 +71,37 @@ Definition sub : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_sub"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mul (evm : Evm) : M unit := (* Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -90,27 +112,37 @@ Definition mul : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_mul"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition div (evm : Evm) : M unit := (* Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -121,25 +153,33 @@ Definition div : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |) in - let* divisor := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - quotient - |) 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 : M unit := +Definition sdiv (evm : Evm) : M unit := (* Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -150,31 +190,39 @@ Definition sdiv : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* divisor := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - quotient + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mod : M unit := +Definition mod (evm : Evm) : M unit := (* Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -185,25 +233,33 @@ Definition mod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - remainder - |) in + |) ]] 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 : M unit := +Definition smod (evm : Evm) : M unit := (* Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -214,31 +270,39 @@ Definition smod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* y := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - remainder + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition addmod : M unit := +Definition addmod (evm : Evm) : M unit := (* Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -249,34 +313,44 @@ Definition addmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +Definition mulmod (evm : Evm) : M unit := (* Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -287,34 +361,44 @@ Definition mulmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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 : M unit := +Definition exp (evm : Evm) : M unit := (* Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -325,39 +409,53 @@ Definition exp : M unit := The current EVM frame. *) - let* base := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent_bits := exponent.["bit_length"] (| - - |) in - let* exponent_bytes := (* TODO expression *) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - pow (| - base, - exponent, - (* 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 - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition signextend : M unit := +Definition signextend (evm : Evm) : M unit := (* Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -368,20 +466,28 @@ Definition signextend : M unit := The current EVM frame. *) - let* byte_num := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/gray_glacier/vm/instructions/bitwise.v index af59c57694..2341fa42db 100644 --- a/coq/ethereum/gray_glacier/vm/instructions/bitwise.v +++ b/coq/ethereum/gray_glacier/vm/instructions/bitwise.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Bitwise Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM bitwise instructions. *) Require ethereum_types.numeric. -Require gray_glacier.vm.gas. -Require gray_glacier.vm.stack. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.stack. -Definition bitwise_and : M unit := +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. @@ -27,24 +29,32 @@ Definition bitwise_and : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_or : M unit := +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. @@ -55,24 +65,32 @@ Definition bitwise_or : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_xor : M unit := +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. @@ -83,24 +101,32 @@ Definition bitwise_xor : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_not : M unit := +Definition bitwise_not (evm : Evm) : M unit := (* Bitwise NOT operation of the top element of the stack. Pushes the result back on the stack. @@ -111,21 +137,27 @@ Definition bitwise_not : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition get_byte : M unit := +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 @@ -137,25 +169,33 @@ Definition get_byte : M unit := The current EVM frame. *) - let* byte_index := stack.pop (| - evm.["stack"] - |) in - let* word := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -164,29 +204,37 @@ Definition bitwise_shl : M unit := evm : The current EVM frame. *) - let* shift := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -195,25 +243,33 @@ Definition bitwise_shr : M unit := evm : The current EVM frame. *) - let* shift := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -222,24 +278,32 @@ Definition bitwise_sar : M unit := evm : The current EVM frame. *) - let* shift := int (| - stack.pop (| - evm.["stack"] - |) - |) in - let* signed_value := stack.pop (| - evm.["stack"] - |).["to_signed"] (| + 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 - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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.v b/coq/ethereum/gray_glacier/vm/instructions/block.v index f8d9360c10..1c04eac1b9 100644 --- a/coq/ethereum/gray_glacier/vm/instructions/block.v +++ b/coq/ethereum/gray_glacier/vm/instructions/block.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Block Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM block instructions. *) Require ethereum_types.numeric. -Require gray_glacier.vm.gas. -Require gray_glacier.vm.stack. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.stack. -Definition block_hash : M unit := +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. @@ -27,27 +29,35 @@ Definition block_hash : M unit := The current EVM frame. *) - let* block_number := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* max_block_number := (* TODO expression *) in + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition coinbase : M unit := +Definition coinbase (evm : Evm) : M unit := (* Push the current block's beneficiary address (address of the block miner) onto the stack. @@ -62,20 +72,24 @@ Definition coinbase : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["coinbase"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition timestamp : M unit := +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. @@ -90,18 +104,22 @@ Definition timestamp : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["env"].["time"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition number (evm : Evm) : M unit := (* Push the current block's number onto the stack. @@ -115,20 +133,24 @@ Definition number : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["number"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition difficulty : M unit := +Definition difficulty (evm : Evm) : M unit := (* Push the current block's difficulty onto the stack. @@ -142,20 +164,24 @@ Definition difficulty : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["difficulty"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_limit : M unit := +Definition gas_limit (evm : Evm) : M unit := (* Push the current block's gas limit onto the stack. @@ -169,20 +195,24 @@ Definition gas_limit : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_limit"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition chain_id : M unit := +Definition chain_id (evm : Evm) : M unit := (* Push the chain id onto the stack. @@ -193,15 +223,19 @@ Definition chain_id : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["chain_id"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/gray_glacier/vm/instructions/comparison.v index 7cef056882..498f90654e 100644 --- a/coq/ethereum/gray_glacier/vm/instructions/comparison.v +++ b/coq/ethereum/gray_glacier/vm/instructions/comparison.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Comparison Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM Comparison instructions. *) Require ethereum_types.numeric. -Require gray_glacier.vm.gas. -Require gray_glacier.vm.stack. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.stack. -Definition less_than : M unit := +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. @@ -27,27 +29,37 @@ Definition less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_less_than : M unit := + |) ]] 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. @@ -57,31 +69,41 @@ Definition signed_less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition greater_than : M unit := + |) ]] 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. @@ -92,27 +114,37 @@ Definition greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_greater_than : M unit := + |) ]] 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. @@ -122,31 +154,41 @@ Definition signed_greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition equal : M unit := + |) ]] 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. @@ -157,27 +199,37 @@ Definition equal : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition is_zero : M unit := + |) ]] 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. @@ -188,19 +240,27 @@ Definition is_zero : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/gray_glacier/vm/instructions/control_flow.v index 1f88e4a395..097ba5b4c8 100644 --- a/coq/ethereum/gray_glacier/vm/instructions/control_flow.v +++ b/coq/ethereum/gray_glacier/vm/instructions/control_flow.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Control Flow Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM control flow instructions. *) Require ethereum_types.numeric. -Require gray_glacier.vm.gas. -Require gray_glacier.vm.exceptions. -Require gray_glacier.vm.stack. +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 : M unit := +Definition stop (evm : Evm) : M unit := (* Stop further execution of EVM code. @@ -29,10 +31,14 @@ Definition stop : M unit := (* TODO statement *) (* TODO statement *) (* TODO assignment *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jump : M unit := +Definition jump (evm : Evm) : M unit := (* Alter the program counter to the location specified by the top of the stack. @@ -43,20 +49,22 @@ Definition jump : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition jumpi : M unit := +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 @@ -68,23 +76,27 @@ Definition jumpi : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* conditional_value := stack.pop (| - evm.["stack"] - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition pc : M unit := +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. @@ -96,20 +108,24 @@ Definition pc : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["pc"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_left : M unit := +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. @@ -121,20 +137,24 @@ Definition gas_left : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["gas_left"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jumpdest : M unit := +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 @@ -147,10 +167,14 @@ Definition jumpdest : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_JUMPDEST - |) in - (* TODO statement *) + |) ]] 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.v b/coq/ethereum/gray_glacier/vm/instructions/environment.v index 7a2b15966a..73f9c217bf 100644 --- a/coq/ethereum/gray_glacier/vm/instructions/environment.v +++ b/coq/ethereum/gray_glacier/vm/instructions/environment.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,15 +16,16 @@ Implementations of the EVM environment related instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require gray_glacier.fork_types. -Require gray_glacier.state. -Require gray_glacier.utils.address. -Require gray_glacier.vm.memory. -Require gray_glacier.vm.exceptions. -Require gray_glacier.vm.gas. -Require gray_glacier.vm.stack. - -Definition address : M unit := +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. @@ -34,20 +36,24 @@ Definition address : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["current_target"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition balance : M unit := +Definition balance (evm : Evm) : M unit := (* Pushes the balance of the given account onto the stack. @@ -57,24 +63,32 @@ Definition balance : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] + 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 - (* TODO statement *) - let* balance := state.get_account (| - evm.["env"].["state"], - address - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition origin : M unit := +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. @@ -86,20 +100,24 @@ Definition origin : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["origin"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition caller : M unit := +Definition caller (evm : Evm) : M unit := (* Pushes the address of the caller onto the stack. @@ -110,20 +128,24 @@ Definition caller : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["caller"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition callvalue : M unit := +Definition callvalue (evm : Evm) : M unit := (* Push the value (in wei) sent with the call onto the stack. @@ -134,18 +156,22 @@ Definition callvalue : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["message"].["value"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition calldataload (evm : Evm) : M unit := (* Push a word (32 bytes) of the input data belonging to the current environment onto the stack. @@ -156,30 +182,38 @@ Definition calldataload : M unit := The current EVM frame. *) - let* start_index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - start_index, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] 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* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - value + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 |) - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition calldatasize : M unit := +Definition calldatasize (evm : Evm) : M unit := (* Push the size of input data in current environment onto the stack. @@ -190,22 +224,26 @@ Definition calldatasize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["message"].["data"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition calldatacopy : M unit := +Definition calldatacopy (evm : Evm) : M unit := (* Copy a portion of the input data in current environment to memory. @@ -218,40 +256,60 @@ Definition calldatacopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* data_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - data_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition codesize (evm : Evm) : M unit := (* Push the size of code running in current environment onto the stack. @@ -262,22 +320,26 @@ Definition codesize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["code"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition codecopy : M unit := +Definition codecopy (evm : Evm) : M unit := (* Copy a portion of the code in current environment to memory. @@ -290,40 +352,60 @@ Definition codecopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["code"], - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition gasprice (evm : Evm) : M unit := (* Push the gas price used in current environment onto the stack. @@ -334,20 +416,24 @@ Definition gasprice : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_price"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition extcodesize : M unit := +Definition extcodesize (evm : Evm) : M unit := (* Push the code size of a given account onto the stack. @@ -357,28 +443,36 @@ Definition extcodesize : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - (* TODO statement *) - let* codesize := ethereum_types.numeric.U256 (| - len (| - state.get_account (| - evm.["env"].["state"], - address - |).["code"] + 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 - do* stack.push (| - evm.["stack"], - codesize - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition extcodecopy : M unit := +Definition extcodecopy (evm : Evm) : M unit := (* Copy a portion of an account's code to memory. @@ -388,46 +482,70 @@ Definition extcodecopy : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - (* TODO statement *) - let* code := state.get_account (| - evm.["env"].["state"], - address - |).["code"] in - let* value := vm.memory.buffer_read (| - code, - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in + 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 : M unit := +Definition returndatasize (evm : Evm) : M unit := (* Pushes the size of the return data buffer onto the stack. @@ -437,22 +555,26 @@ Definition returndatasize : M unit := The current EVM frame. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["return_data"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition returndatacopy : M unit := +Definition returndatacopy (evm : Evm) : M unit := (* Copies data from the return data buffer code to memory @@ -461,37 +583,57 @@ Definition returndatacopy : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* return_data_start_position := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - (* TODO statement *) - let* value := (* TODO expression *) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in + |) ]] 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 : M unit := +Definition extcodehash (evm : Evm) : M unit := (* Returns the keccak256 hash of a contract’s bytecode Parameters @@ -499,25 +641,33 @@ Definition extcodehash : M unit := evm : The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] + 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 - (* TODO statement *) - let* account := state.get_account (| - evm.["env"].["state"], - address - |) in - (* TODO statement *) - do* stack.push (| - evm.["stack"], - codehash - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition self_balance : M unit := +Definition self_balance (evm : Evm) : M unit := (* Pushes the balance of the current address to the stack. @@ -528,22 +678,28 @@ Definition self_balance : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_FAST_STEP - |) in - let* balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition base_fee (evm : Evm) : M unit := (* Pushes the base fee of the current block on to the stack. @@ -554,15 +710,19 @@ Definition base_fee : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["base_fee_per_gas"] + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/gray_glacier/vm/instructions/keccak.v index 416b27d9c9..6efe8c5fd9 100644 --- a/coq/ethereum/gray_glacier/vm/instructions/keccak.v +++ b/coq/ethereum/gray_glacier/vm/instructions/keccak.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Keccak Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM keccak instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require gray_glacier.vm.gas. -Require gray_glacier.vm.memory. -Require gray_glacier.vm.stack. +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 : M unit := +Definition keccak (evm : Evm) : M unit := (* Pushes to the stack the Keccak-256 hash of a region of memory. @@ -32,36 +34,56 @@ Definition keccak : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* word_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in - let* hash := ethereum.crypto.hash.keccak256 (| - data - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/gray_glacier/vm/instructions/log.v index 91a8aefda9..2ed6fac93f 100644 --- a/coq/ethereum/gray_glacier/vm/instructions/log.v +++ b/coq/ethereum/gray_glacier/vm/instructions/log.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Logging Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,13 +15,14 @@ Implementations of the EVM logging instructions. Require functools. Require ethereum_types.numeric. -Require gray_glacier.blocks. -Require gray_glacier.vm.exceptions. -Require gray_glacier.vm.gas. -Require gray_glacier.vm.memory. -Require gray_glacier.vm.stack. +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 : M unit := +Definition log_n (evm : Evm) (num_topics : U256) : M unit := (* Appends a log entry, having `num_topics` topics, to the evm logs. @@ -35,27 +37,43 @@ Definition log_n : M unit := The number of topics to be included in the log entry. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* topics := (* TODO expression *) in + 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 *) - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in (* TODO statement *) - let* log_entry := blocks.Log (| + do* M.assign "log_entry" [[ + blocks.Log ~(| - |) in + |) in + ]] in (* TODO assignment *) - (* 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/memory.v b/coq/ethereum/gray_glacier/vm/instructions/memory.v index de111d5c5d..d9fac1b733 100644 --- a/coq/ethereum/gray_glacier/vm/instructions/memory.v +++ b/coq/ethereum/gray_glacier/vm/instructions/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM Memory instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require gray_glacier.vm.gas. -Require gray_glacier.vm.memory. -Require gray_glacier.vm.stack. +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 : M unit := +Definition mstore (evm : Evm) : M unit := (* Stores a word to memory. This also expands the memory, if the memory is @@ -30,32 +32,44 @@ Definition mstore : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* memory.memory_write (| - evm.["memory"], - start_position, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mstore8 (evm : Evm) : M unit := (* Stores a byte to memory. This also expands the memory, if the memory is @@ -67,33 +81,47 @@ Definition mstore8 : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ (* TODO expression *) - |) in - do* memory.memory_write (| - evm.["memory"], - start_position, - normalized_bytes_value - |) in - (* TODO statement *) - + ]] 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 : M unit := +Definition mload (evm : Evm) : M unit := (* Load word from memory. @@ -103,35 +131,47 @@ Definition mload : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.memory_read_bytes (| - evm.["memory"], - start_position, - ethereum_types.numeric.U256 (| - (* 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 - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition msize : M unit := +Definition msize (evm : Evm) : M unit := (* Push the size of active memory in bytes onto the stack. @@ -142,17 +182,21 @@ Definition msize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["memory"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/gray_glacier/vm/instructions/stack.v index 568e61ea04..309349a16f 100644 --- a/coq/ethereum/gray_glacier/vm/instructions/stack.v +++ b/coq/ethereum/gray_glacier/vm/instructions/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM stack related instructions. Require functools. Require ethereum_types.numeric. -Require gray_glacier.vm.exceptions. -Require gray_glacier.vm.gas. -Require 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.memory. -Definition pop : M unit := +Definition pop (evm : Evm) : M unit := (* Remove item from stack. @@ -28,18 +30,22 @@ Definition pop : M unit := The current EVM frame. *) - do* stack.["pop"] (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in + |) ]] in (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition push_n : M unit := +Definition push_n (evm : Evm) (num_bytes : int) : M unit := (* Pushes a N-byte immediate onto the stack. @@ -54,29 +60,33 @@ Definition push_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - evm.["code"], - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - num_bytes + |) ]] 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 - do* stack.["push"] (| - evm.["stack"], - data_to_push - |) in - (* TODO statement *) - - -Definition dup_n : M unit := + |) 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. @@ -91,20 +101,26 @@ Definition dup_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - let* data_to_duplicate := (* TODO expression *) in - do* stack.["push"] (| - evm.["stack"], - data_to_duplicate - |) 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 : M unit := +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. @@ -123,11 +139,15 @@ Definition swap_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - (* 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/storage.v b/coq/ethereum/gray_glacier/vm/instructions/storage.v index e6c64412e9..ecf70597e2 100644 --- a/coq/ethereum/gray_glacier/vm/instructions/storage.v +++ b/coq/ethereum/gray_glacier/vm/instructions/storage.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Storage Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,12 +14,13 @@ Implementations of the EVM storage related instructions. *) Require ethereum_types.numeric. -Require gray_glacier.state. -Require gray_glacier.vm.exceptions. -Require gray_glacier.vm.gas. -Require gray_glacier.vm.stack. +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 : M unit := +Definition sload (evm : Evm) : M unit := (* Loads to the stack, the value corresponding to a certain key from the storage of the current account. @@ -29,25 +31,33 @@ Definition sload : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in + |) in + ]] in (* TODO statement *) - let* value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) 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 : M unit := +Definition sstore (evm : Evm) : M unit := (* Stores a value at a certain key in the current context's storage. @@ -57,41 +67,55 @@ Definition sstore : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in (* TODO statement *) - let* original_value := state.get_storage_original (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - let* current_value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - let* gas_cost := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in + M.get_local ~(| "gas_cost" |) + |) ]] in (* TODO statement *) - do* state.set_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key, - new_value - |) 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.v b/coq/ethereum/gray_glacier/vm/instructions/system.v index 0d1d237a2a..948bccc517 100644 --- a/coq/ethereum/gray_glacier/vm/instructions/system.v +++ b/coq/ethereum/gray_glacier/vm/instructions/system.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) System Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,57 +16,72 @@ Implementations of the EVM system related instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require gray_glacier.fork_types. -Require gray_glacier.state. -Require gray_glacier.utils.address. -Require gray_glacier.vm.exceptions. -Require gray_glacier.vm.gas. -Require gray_glacier.vm.memory. -Require gray_glacier.vm.stack. - -Definition generic_create : M unit := +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* evm.["accessed_addresses"].["add"] (| + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "add" |) ~(| contract_address - |) in - let* create_message_gas := gas.max_message_call_gas (| - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |) - |) in - (* TODO statement *) + |) ]] 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 *) - let* sender_address := evm.["message"].["current_target"] in - let* sender := state.get_account (| - evm.["env"].["state"], - sender_address - |) in - (* TODO statement *) - (* TODO statement *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) in - do* state.increment_nonce (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |) in - let* child_message := Message (| - - |) in - let* child_evm := process_create_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - - -Definition create : M unit := + 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. @@ -74,42 +90,58 @@ Definition create : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_contract_address (| - evm.["message"].["current_target"], - state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["nonce"] - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition create2 (evm : Evm) : M unit := (* Creates a new account with associated code. @@ -121,50 +153,70 @@ Definition create2 : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* salt := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* call_data_words := (* TODO expression *) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_create2_contract_address (| - evm.["message"].["current_target"], - salt, - memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size - |) in - (* TODO statement *) - + 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_ : M unit := +Definition return_ (evm : Evm) : M unit := (* Halts execution returning output data. @@ -173,66 +225,84 @@ Definition return_ : M unit := evm : The current EVM frame. *) - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) + |) ]] 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 : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_input_start_position, - memory_input_size - |) in - let* code := state.get_account (| - evm.["env"].["state"], - code_address - |).["code"] in - let* child_message := Message (| - - |) in - let* child_evm := process_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - let* actual_output_size := min (| - memory_output_size, - ethereum_types.numeric.U256 (| - len (| - child_evm.["output"] + 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 - do* memory.memory_write (| - evm.["memory"], + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), memory_output_start_position, (* TODO expression *) - |) in + |) ]] in + M.pure tt. - -Definition call : M unit := +Definition call (evm : Evm) : M unit := (* Message-call into an account. @@ -241,62 +311,92 @@ Definition call : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* create_gas_cost := (* TODO expression *) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition callcode (evm : Evm) : M unit := (* Message-call into this account with alternative account’s code. @@ -305,61 +405,91 @@ Definition callcode : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* to := evm.["message"].["current_target"] in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) - (* TODO statement *) - + |) ]] 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 : M unit := +Definition selfdestruct (evm : Evm) : M unit := (* Halt execution and register account for later deletion. @@ -368,49 +498,59 @@ Definition selfdestruct : M unit := evm : The current EVM frame. *) - let* beneficiary := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* gas_cost := gas.GAS_SELF_DESTRUCT in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - (* TODO statement *) - let* originator := evm.["message"].["current_target"] in - let* beneficiary_balance := state.get_account (| - evm.["env"].["state"], - beneficiary - |).["balance"] in - let* originator_balance := state.get_account (| - evm.["env"].["state"], - originator - |).["balance"] in - do* state.set_account_balance (| - evm.["env"].["state"], - beneficiary, + 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 (| - evm.["env"].["state"], - originator, - ethereum_types.numeric.U256 (| - (* 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* evm.["accounts_to_delete"].["add"] (| - originator - |) in + |) ]] 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 : M unit := +Definition delegatecall (evm : Evm) : M unit := (* Message-call into an account. @@ -419,67 +559,89 @@ Definition delegatecall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - access_gas_cost - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - evm.["message"].["value"], - evm.["message"].["caller"], - evm.["message"].["current_target"], - code_address, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition staticcall (evm : Evm) : M unit := (* Message-call into an account. @@ -488,69 +650,91 @@ Definition staticcall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - access_gas_cost - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - ethereum_types.numeric.U256 (| - (* TODO expression *) + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 |), - evm.["message"].["current_target"], - to, - to, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +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 @@ -559,27 +743,37 @@ Definition revert : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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, - extend_memory.["cost"] - |) in - (* TODO statement *) - let* output := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in + 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.v b/coq/ethereum/gray_glacier/vm/interpreter.v index 77619bf01a..b4122d90ba 100644 --- a/coq/ethereum/gray_glacier/vm/interpreter.v +++ b/coq/ethereum/gray_glacier/vm/interpreter.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Interpreter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +18,18 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.trace. -Require gray_glacier.blocks. -Require gray_glacier.fork_types. -Require gray_glacier.state. -Require gray_glacier.vm. -Require gray_glacier.vm.gas. -Require gray_glacier.vm.precompiled_contracts.mapping. -Require gray_glacier.vm.exceptions. -Require gray_glacier.vm.instructions. -Require gray_glacier.vm.runtime. - -Definition process_message_call : M unit := +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`. @@ -47,19 +49,21 @@ Definition process_message_call : M unit := *) (* TODO statement *) (* TODO statement *) - let* tx_end := ethereum.trace.TransactionEnd (| - (* TODO expression *), - evm.["output"], - evm.["error"] - |) in - do* ethereum.trace.evm_trace (| - evm, - tx_end - |) in + 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 : M unit := +Definition process_create_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -75,30 +79,32 @@ Definition process_create_message : M unit := evm: :py:class:`~ethereum.london.vm.Evm` Items containing execution specific objects. *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.destroy_storage (| - env.["state"], - message.["current_target"] - |) in - do* state.mark_account_created (| - env.["state"], - message.["current_target"] - |) in - do* state.increment_nonce (| - env.["state"], - message.["current_target"] - |) in - let* evm := process_message (| - message, - env - |) in + 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 : M unit := +Definition process_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -115,23 +121,25 @@ Definition process_message : M unit := Items containing execution specific objects *) (* TODO statement *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.touch_account (| - env.["state"], - message.["current_target"] - |) in + 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 *) - let* evm := execute_code (| - message, - env - |) in + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition execute_code : M unit := +Definition execute_code (message : Message) (env : Environment) : M Evm := (* Executes bytecode present in the `message`. @@ -147,13 +155,19 @@ Definition execute_code : M unit := evm: `ethereum.vm.EVM` Items containing execution specific objects *) - let* code := message.["code"] in - let* valid_jump_destinations := runtime.get_valid_jump_destinations (| - code - |) in - let* evm := Evm (| - - |) in + 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.v b/coq/ethereum/gray_glacier/vm/memory.v index 94b6a44639..88b516318f 100644 --- a/coq/ethereum/gray_glacier/vm/memory.v +++ b/coq/ethereum/gray_glacier/vm/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.byte. -Definition memory_write : M unit := +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := (* Writes to memory. @@ -30,9 +31,9 @@ Definition memory_write : M unit := Data to write to memory. *) (* TODO assignment *) + M.pure tt. - -Definition memory_read_bytes : M unit := +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := (* Read bytes from memory. @@ -51,9 +52,9 @@ Definition memory_read_bytes : M unit := Data read from memory. *) (* TODO statement *) + M.pure tt. - -Definition buffer_read : M unit := +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := (* Read bytes from a buffer. Padding with zeros if necessary. @@ -72,4 +73,4 @@ Definition buffer_read : M unit := Data read from memory. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/__init__.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/__init__.v index 41776f4ca0..ab3f148773 100644 --- a/coq/ethereum/gray_glacier/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,4 +14,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require gray_glacier.utils.hexadecimal. +Require ethereum.gray_glacier.utils.hexadecimal. diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.v index 566d466ee5..e49a78fed5 100644 --- a/coq/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.v +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,12 +15,12 @@ Implementation of the ALT_BN128 precompiled contracts. Require ethereum_types.numeric. Require ethereum.crypto.alt_bn128. -Require gray_glacier.vm. -Require gray_glacier.vm.gas. -Require gray_glacier.vm.memory. -Require gray_glacier.vm.exceptions. +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 : M unit := +Definition alt_bn128_add (evm : Evm) : M unit := (* The ALT_BN128 addition precompiled contract. @@ -28,76 +29,96 @@ Definition alt_bn128_add : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* x1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x1_bytes - |) - |) in - let* y1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y1_bytes - |) - |) in + 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 *) - let* p := (* TODO expression *) in + do* M.assign "p" [[ + (* TODO expression *) in + ]] in (* TODO assignment *) + M.pure tt. - -Definition alt_bn128_mul : M unit := +Definition alt_bn128_mul (evm : Evm) : M unit := (* The ALT_BN128 multiplication precompiled contract. @@ -106,63 +127,77 @@ Definition alt_bn128_mul : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* n := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) (* TODO statement *) - let* p := p0.["mul_by"] (| - n - |) in + 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 : M unit := +Definition alt_bn128_pairing_check (evm : Evm) : M unit := (* The ALT_BN128 pairing check precompiled contract. @@ -171,17 +206,21 @@ Definition alt_bn128_pairing_check : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 (| + ethereum_types.numeric.Uint ~(| (* TODO expression *) |) - |) in + |) ]] in (* TODO statement *) - let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.v index 583aa354a4..61824c970a 100644 --- a/coq/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.v +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,11 @@ Implementation of the `Blake2` precompiled contract. *) Require ethereum.crypto.blake2. -Require gray_glacier.vm. -Require gray_glacier.vm.gas. -Require gray_glacier.vm.exceptions. +Require ethereum.gray_glacier.vm. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.exceptions. -Definition blake2f : M unit := +Definition blake2f (evm : Evm) : M unit := (* Writes the Blake2 hash to output. @@ -26,16 +27,20 @@ Definition blake2f : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in (* TODO statement *) - let* blake2b := ethereum.crypto.blake2.Blake2b (| + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| - |) in + |) in + ]] in (* TODO assignment *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, (* TODO expression *) - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.v index 1ba9ae7ae9..f22e39c0ac 100644 --- a/coq/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.v +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,11 +17,11 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require gray_glacier.vm. -Require gray_glacier.vm.gas. -Require gray_glacier.vm.memory. +Require ethereum.gray_glacier.vm. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.memory. -Definition ecrecover : M unit := +Definition ecrecover (evm : Evm) : M unit := (* Decrypts the address using elliptic curve DSA recovery mechanism and writes the address to output. @@ -30,64 +31,80 @@ Definition ecrecover : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* message_hash_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* message_hash := ethereum.crypto.hash.Hash32 (| - message_hash_bytes - |) in - let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + ethereum_types.numeric.U256 ~(| + 32 |) - |) - |) in - let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 + ]] 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 *) - let* address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/identity.v index bb810f154b..71abf77228 100644 --- a/coq/ethereum/gray_glacier/vm/precompiled_contracts/identity.v +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/identity.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,10 @@ Implementation of the `IDENTITY` precompiled contract. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require gray_glacier.vm. -Require gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm. +Require ethereum.gray_glacier.vm.gas. -Definition identity : M unit := +Definition identity (evm : Evm) : M unit := (* Writes the message data to output. @@ -26,11 +27,15 @@ Definition identity : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/mapping.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/mapping.v index 41a63293b6..fd67a86d12 100644 --- a/coq/ethereum/gray_glacier/vm/precompiled_contracts/mapping.v +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/mapping.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Mapping of precompiled contracts their implementations. *) Require typing. -Require gray_glacier.fork_types. -Require gray_glacier.vm.precompiled_contracts.alt_bn128. -Require gray_glacier.vm.precompiled_contracts.blake2f. -Require gray_glacier.vm.precompiled_contracts.ecrecover. -Require gray_glacier.vm.precompiled_contracts.identity. -Require gray_glacier.vm.precompiled_contracts.modexp. -Require gray_glacier.vm.precompiled_contracts.ripemd160. -Require gray_glacier.vm.precompiled_contracts.sha256. +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.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/modexp.v index 8a4434582b..dd5605150e 100644 --- a/coq/ethereum/gray_glacier/vm/precompiled_contracts/modexp.v +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/modexp.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,100 +15,120 @@ Implementation of the `MODEXP` precompiled contract. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require gray_glacier.vm. -Require gray_glacier.vm.gas. -Require gray_glacier.vm.memory. +Require ethereum.gray_glacier.vm. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.memory. -Definition modexp : M unit := +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. *) - let* data := evm.["message"].["data"] in - let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) - |) in - let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 - let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* exp_start := (* TODO expression *) in - let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - min (| - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 |), - exp_length + ethereum_types.numeric.U256 ~(| + 32 + |) |) - |) - |) in - do* vm.gas.charge_gas (| + |) 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, - gas_cost (| - base_length, - modulus_length, - exp_length, - exp_head + 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 + |) ]] in (* TODO statement *) - let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - base_length - |) - |) in - let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - exp_length - |) - |) in - let* modulus_start := (* TODO expression *) in - let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - modulus_start, - modulus_length - |) - |) in + 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 : M unit := +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := (* Estimate the complexity of performing a modular exponentiation. @@ -126,19 +147,23 @@ Definition complexity : M unit := complexity : `Uint` Complexity of performing the operation. *) - let* max_length := max (| - ethereum_types.numeric.Uint (| - base_length - |), - ethereum_types.numeric.Uint (| - modulus_length - |) - |) in - let* words := (* TODO expression *) in + 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 : M unit := +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := (* Calculate the number of iterations required to perform a modular exponentiation. @@ -161,9 +186,9 @@ Definition iterations : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition gas_cost : M unit := +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. @@ -189,15 +214,23 @@ Definition gas_cost : M unit := gas_cost : `Uint` Gas required for performing the operation. *) - let* multiplication_complexity := complexity (| - base_length, - modulus_length - |) in - let* iteration_count := iterations (| - exponent_length, - exponent_head - |) in - let* cost := (* TODO expression *) in - (* TODO statement *) + 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.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.v index bc5e73dd3c..fe2c66bbe6 100644 --- a/coq/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.v +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `RIPEMD160` precompiled contract. *) -Definition ripemd160 : M unit := +Definition ripemd160 (evm : Evm) : M unit := (* Writes the ripemd160 hash to output. @@ -22,21 +23,29 @@ Definition ripemd160 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 - let* hash_bytes := hashlib.["new"] (| - (* TODO expression *), - data - |).["digest"] (| - - |) in - let* padded_hash := left_pad_zero_bytes (| - hash_bytes, - (* TODO expression *) - |) in + |) ]] 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.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/sha256.v index da6972d411..3ba3ffe7aa 100644 --- a/coq/ethereum/gray_glacier/vm/precompiled_contracts/sha256.v +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/sha256.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `SHA256` precompiled contract. *) -Definition sha256 : M unit := +Definition sha256 (evm : Evm) : M unit := (* Writes the sha256 hash to output. @@ -22,11 +23,15 @@ Definition sha256 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/runtime.v b/coq/ethereum/gray_glacier/vm/runtime.v index 37ec67279f..c8f96e69b4 100644 --- a/coq/ethereum/gray_glacier/vm/runtime.v +++ b/coq/ethereum/gray_glacier/vm/runtime.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Runtime Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Runtime related operations used while executing EVM code. Require typing. Require ethereum_types.numeric. -Require gray_glacier.vm.instructions. +Require ethereum.gray_glacier.vm.instructions. -Definition get_valid_jump_destinations : M unit := +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := (* Analyze the evm code to obtain the set of valid jump destinations. @@ -38,12 +39,16 @@ Definition get_valid_jump_destinations : M unit := valid_jump_destinations: `Set[Uint]` The set of valid jump destinations in the code. *) - let* valid_jump_destinations := set (| - - |) in - let* pc := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/gray_glacier/vm/stack.v index f47503ffda..11fb88ad79 100644 --- a/coq/ethereum/gray_glacier/vm/stack.v +++ b/coq/ethereum/gray_glacier/vm/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Implementation of the stack operators for the EVM. Require typing. Require ethereum_types.numeric. -Require gray_glacier.vm.exceptions. +Require ethereum.gray_glacier.vm.exceptions. -Definition pop : M unit := +Definition pop (stack : (* TODO type *)) : M U256 := (* Pops the top item off of `stack`. @@ -33,9 +34,9 @@ Definition pop : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition push : M unit := +Definition push (stack : (* TODO type *)) (value : U256) : M unit := (* Pushes `value` onto `stack`. @@ -50,4 +51,4 @@ Definition push : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/homestead/__init__.v b/coq/ethereum/homestead/__init__.v index ed0ab80f91..b212056d27 100644 --- a/coq/ethereum/homestead/__init__.v +++ b/coq/ethereum/homestead/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* The Homestead fork increases the gas cost of creating contracts, restricts the range of valid ECDSA signatures for transactions (but not precompiles), tweaks diff --git a/coq/ethereum/homestead/blocks.v b/coq/ethereum/homestead/blocks.v index 530db3d996..d9bce5f5a8 100644 --- a/coq/ethereum/homestead/blocks.v +++ b/coq/ethereum/homestead/blocks.v @@ -1,3 +1,4 @@ +(* 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 @@ -14,6 +15,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. -Require homestead.fork_types. -Require homestead.transactions. +Require ethereum.crypto.hash. +Require ethereum.homestead.fork_types. +Require ethereum.homestead.transactions. diff --git a/coq/ethereum/homestead/bloom.v b/coq/ethereum/homestead/bloom.v index 0b169c3e69..651168d395 100644 --- a/coq/ethereum/homestead/bloom.v +++ b/coq/ethereum/homestead/bloom.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Logs Bloom ^^^^^^^^^^^^^^^^^^^ @@ -19,10 +20,10 @@ eliminating blocks and receipts from their search. Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require homestead.blocks. -Require homestead.fork_types. +Require ethereum.homestead.blocks. +Require ethereum.homestead.fork_types. -Definition add_to_bloom : M unit := +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := (* Add a bloom entry to the bloom filter (`bloom`). @@ -37,13 +38,15 @@ Definition add_to_bloom : M unit := bloom_entry : An entry which is to be added to bloom filter. *) - let* hash := ethereum.crypto.hash.keccak256 (| - bloom_entry - |) in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition logs_bloom : M unit := +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := (* Obtain the logs bloom from a list of log entries. @@ -63,4 +66,4 @@ Definition logs_bloom : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/homestead/fork.v b/coq/ethereum/homestead/fork.v index bcccf731cd..0da6d386d2 100644 --- a/coq/ethereum/homestead/fork.v +++ b/coq/ethereum/homestead/fork.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^ @@ -20,16 +21,18 @@ Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.ethash. Require ethereum.exceptions. -Require homestead.blocks. -Require homestead.bloom. -Require homestead.fork_types. -Require homestead.state. -Require homestead.transactions. -Require homestead.trie. -Require homestead.utils.message. -Require homestead.vm.interpreter. - -Definition apply_fork : M unit := +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. @@ -49,9 +52,9 @@ Definition apply_fork : M unit := Upgraded block chain object for this hard fork. *) (* TODO statement *) + M.pure tt. - -Definition get_last_256_block_hashes : M unit := +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. @@ -71,22 +74,28 @@ Definition get_last_256_block_hashes : M unit := recent_block_hashes : `List[Hash32]` Hashes of the recent 256 blocks in order of increasing block number. *) - let* recent_blocks := (* TODO expression *) in - (* TODO statement *) - let* recent_block_hashes := (* TODO expression *) in - (* TODO statement *) - let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *).["header"] - |) - |) in - do* recent_block_hashes.["append"] (| - most_recent_block_hash - |) in - (* TODO statement *) - - -Definition state_transition : M unit := + 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. @@ -108,41 +117,45 @@ Definition state_transition : M unit := block : Block to apply to `chain`. *) - let* parent_header := (* TODO expression *).["header"] in - do* validate_header (| - block.["header"], - parent_header - |) in - do* validate_ommers (| - block.["ommers"], - block.["header"], + 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 - let* apply_body_output := apply_body (| - chain.["state"], - get_last_256_block_hashes (| - chain - |), - block.["header"].["coinbase"], - block.["header"].["number"], - block.["header"].["gas_limit"], - block.["header"].["timestamp"], - block.["header"].["difficulty"], - block.["transactions"], - block.["ommers"] - |) in + |) ]] 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* chain.["blocks"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| block - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition validate_header : M unit := +Definition validate_header (header : Header) (parent_header : Header) : M unit := (* Verifies a block header. @@ -164,25 +177,29 @@ Definition validate_header : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* block_difficulty := calculate_block_difficulty (| - header.["number"], - header.["timestamp"], - parent_header.["timestamp"], - parent_header.["difficulty"] - |) in + 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 *) - let* block_parent_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - parent_header - |) - |) in + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in (* TODO statement *) - do* validate_proof_of_work (| + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| header - |) in + |) ]] in + M.pure tt. - -Definition generate_header_hash_for_pow : M unit := +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. @@ -205,11 +222,13 @@ Definition generate_header_hash_for_pow : M unit := hash : `Hash32` The PoW valid rlp hash of the passed in header. *) - let* header_data_without_pow_artefacts := (* TODO expression *) in + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition validate_proof_of_work : M unit := +Definition validate_proof_of_work (header : Header) : M unit := (* Validates the Proof of Work constraints. @@ -224,19 +243,25 @@ Definition validate_proof_of_work : M unit := header : Header of interest. *) - let* header_hash := generate_header_hash_for_pow (| - header - |) in - let* cache := ethereum.ethash.generate_cache (| - header.["number"] - |) in + 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 *) - let* limit := (* TODO expression *) in + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition check_transaction : M unit := +Definition check_transaction (tx : Transaction) (gas_available : Uint) : M Address := (* Check if the transaction is includable in the block. @@ -258,13 +283,15 @@ Definition check_transaction : M unit := If the transaction is not includable. *) (* TODO statement *) - let* sender_address := recover_sender (| - tx - |) in + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + tx + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition make_receipt : M unit := +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. @@ -285,13 +312,15 @@ Definition make_receipt : M unit := receipt : The receipt for the transaction. *) - let* receipt := blocks.Receipt (| + do* M.assign "receipt" [[ + blocks.Receipt ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition apply_body : M unit := +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. @@ -330,25 +359,31 @@ Definition apply_body : M unit := apply_body_output : `ApplyBodyOutput` Output of applying the block body to the state. *) - let* gas_available := block_gas_limit in + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - do* pay_rewards (| + do* [[ M.get_local ~(| "pay_rewards" |) ~(| state, block_number, coinbase, ommers - |) in - let* block_gas_used := (* TODO expression *) in - let* block_logs_bloom := bloom.logs_bloom (| - block_logs - |) in - (* TODO statement *) - - -Definition validate_ommers : M unit := + |) ]] 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. @@ -370,23 +405,31 @@ Definition validate_ommers : M unit := chain : History and current state. *) - let* block_hash := rlp.["rlp_hash"] (| - block_header - |) in + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* ommers_hashes := (* TODO expression *) in + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* recent_canonical_blocks := (* TODO expression *) in - let* recent_canonical_block_hashes := (* TODO expression *) in + 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 : M unit := +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. @@ -412,21 +455,25 @@ Definition pay_rewards : M unit := ommers : List of ommers mentioned in the current block. *) - let* ommer_count := ethereum_types.numeric.U256 (| - len (| - ommers - |) - |) in - let* miner_reward := (* TODO expression *) in - do* state.create_ether (| + 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, - miner_reward - |) in + M.get_local ~(| "miner_reward" |) + |) ]] in (* TODO statement *) + M.pure tt. - -Definition process_transaction : M unit := +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := (* Execute a transaction against the provided environment. @@ -454,67 +501,95 @@ Definition process_transaction : M unit := Logs generated during execution. *) (* TODO statement *) - let* sender := env.["origin"] in - let* sender_account := state.get_account (| - env.["state"], - sender - |) in - let* gas_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* gas := (* TODO expression *) in - do* state.increment_nonce (| - env.["state"], - sender - |) in - let* sender_balance_after_gas_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - ethereum_types.numeric.U256 (| - sender_balance_after_gas_fee + 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 - let* message := utils.message.prepare_message (| - sender, - tx.["to"], - tx.["value"], - tx.["data"], - gas, - env - |) in - let* output := vm.interpreter.process_message_call (| - message, - env - |) in - let* gas_used := (* TODO expression *) in - let* gas_refund := min (| - (* TODO expression *), - ethereum_types.numeric.Uint (| - output.["refund_counter"] - |) - |) in - let* gas_refund_amount := (* TODO expression *) in - let* transaction_fee := (* TODO expression *) in - let* total_gas_used := (* TODO expression *) in - let* sender_balance_after_refund := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - sender_balance_after_refund - |) in - let* coinbase_balance_after_mining_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - env.["coinbase"], - coinbase_balance_after_mining_fee - |) in - (* TODO statement *) - (* TODO statement *) - - -Definition validate_transaction : M unit := + |) ]] 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. @@ -542,9 +617,9 @@ Definition validate_transaction : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition calculate_intrinsic_cost : M unit := +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := (* Calculates the gas that is charged before execution is started. @@ -567,13 +642,15 @@ Definition calculate_intrinsic_cost : M unit := verified : `ethereum.base_types.Uint` The intrinsic cost of the transaction. *) - let* data_cost := (* TODO expression *) in + do* M.assign "data_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition recover_sender : M unit := +Definition recover_sender (tx : Transaction) : M Address := (* Extracts the sender address from a transaction. @@ -597,18 +674,20 @@ Definition recover_sender : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* public_key := ethereum.crypto.elliptic_curve.secp256k1_recover (| - r, - s, - (* TODO expression *), - signing_hash (| - tx - |) - |) in + 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 : M unit := +Definition signing_hash (tx : Transaction) : M Hash32 := (* Compute the hash of a transaction used in the signature. @@ -627,9 +706,9 @@ Definition signing_hash : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition compute_header_hash : M unit := +Definition compute_header_hash (header : Header) : M Hash32 := (* Computes the hash of a block header. @@ -662,9 +741,9 @@ Definition compute_header_hash : M unit := Hash of the header. *) (* TODO statement *) + M.pure tt. - -Definition check_gas_limit : M unit := +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := (* Validates the gas limit for a block. @@ -692,14 +771,16 @@ Definition check_gas_limit : M unit := check : `bool` True if gas limit constraints are satisfied, False otherwise. *) - let* max_adjustment_delta := (* TODO expression *) in + 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 : M unit := +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. @@ -736,9 +817,15 @@ Definition calculate_block_difficulty : M unit := difficulty : `ethereum.base_types.Uint` Computed difficulty for a block. *) - let* offset := (* TODO expression *) in - let* difficulty := (* TODO expression *) in - let* num_bomb_periods := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - + 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.v b/coq/ethereum/homestead/fork_types.v index 14de99d5e5..d84cffdf45 100644 --- a/coq/ethereum/homestead/fork_types.v +++ b/coq/ethereum/homestead/fork_types.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Types ^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. +Require ethereum.__init__. +Require ethereum.crypto.hash. -Definition encode_account : M unit := +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := (* Encode `Account` dataclass. @@ -26,4 +28,4 @@ Definition encode_account : M unit := encoded without providing a storage root. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/homestead/state.v b/coq/ethereum/homestead/state.v index 2c93111c7a..ca861a3cb9 100644 --- a/coq/ethereum/homestead/state.v +++ b/coq/ethereum/homestead/state.v @@ -1,3 +1,4 @@ +(* Generated *) (* State ^^^^^ @@ -22,10 +23,10 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require homestead.fork_types. -Require homestead.trie. +Require ethereum.homestead.fork_types. +Require ethereum.homestead.trie. -Definition close_state : M unit := +Definition close_state (state : State) : M unit := (* Free resources held by the state. Used by optimized implementations to release file descriptors. @@ -33,9 +34,9 @@ Definition close_state : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition begin_transaction : M unit := +Definition begin_transaction (state : State) : M unit := (* Start a state transaction. @@ -47,12 +48,12 @@ Definition begin_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition commit_transaction : M unit := +Definition commit_transaction (state : State) : M unit := (* Commit a state transaction. @@ -61,12 +62,12 @@ Definition commit_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["pop"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| - |) in + |) ]] in + M.pure tt. - -Definition rollback_transaction : M unit := +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. @@ -77,9 +78,9 @@ Definition rollback_transaction : M unit := The state. *) (* TODO assignment *) + M.pure tt. - -Definition get_account : M unit := +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. @@ -99,14 +100,16 @@ Definition get_account : M unit := account : `Account` Account at address. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition get_account_optional : M unit := +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. @@ -123,14 +126,16 @@ Definition get_account_optional : M unit := account : `Account` Account at address. *) - let* account := trie.trie_get (| - state.["_main_trie"], - address - |) in + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition set_account : M unit := +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()`). @@ -144,14 +149,14 @@ Definition set_account : M unit := account : `Account` Account to set at address. *) - do* trie.trie_set (| - state.["_main_trie"], + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), address, account - |) in - + |) ]] in + M.pure tt. -Definition destroy_account : M unit := +Definition destroy_account (state : State) (address : Address) : M unit := (* Completely remove the account at `address` and all of its storage. @@ -166,18 +171,18 @@ Definition destroy_account : M unit := address : `Address` Address of account to destroy. *) - do* destroy_storage (| + do* [[ M.get_local ~(| "destroy_storage" |) ~(| state, address - |) in - do* set_account (| + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - (* TODO expression *) - |) in - + tt + |) ]] in + M.pure tt. -Definition destroy_storage : M unit := +Definition destroy_storage (state : State) (address : Address) : M unit := (* Completely remove the storage at `address`. @@ -189,9 +194,9 @@ Definition destroy_storage : M unit := Address of account whose storage is to be deleted. *) (* TODO statement *) + M.pure tt. - -Definition get_storage : M unit := +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. @@ -210,19 +215,23 @@ Definition get_storage : M unit := value : `U256` Value at the key. *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition set_storage : M unit := +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. @@ -239,19 +248,21 @@ Definition set_storage : M unit := Value to set at the key. *) (* TODO statement *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - do* trie.trie_set (| - trie, + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), key, value - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition storage_root : M unit := +Definition storage_root (state : State) (address : Address) : M Root := (* Calculate the storage root of an account. @@ -269,9 +280,9 @@ Definition storage_root : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition state_root : M unit := +Definition state_root (state : State) : M Root := (* Calculate the state root. @@ -288,9 +299,9 @@ Definition state_root : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition account_exists : M unit := +Definition account_exists (state : State) (address : Address) : M bool := (* Checks if an account exists in the state trie @@ -307,9 +318,9 @@ Definition account_exists : M unit := True if account exists in the state trie, False otherwise *) (* TODO statement *) + M.pure tt. - -Definition account_has_code_or_nonce : M unit := +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := (* Checks if an account has non zero nonce or non empty code @@ -326,49 +337,51 @@ Definition account_has_code_or_nonce : M unit := True if if an account has non zero nonce or non empty code, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition modify_state : M unit := +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := (* Modify an `Account` in the `State`. *) - do* set_account (| + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - ethereum_types.frozen.modify (| - get_account (| + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| state, address |), f |) - |) in + |) ]] in + M.pure tt. - -Definition move_ether : M unit := +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := (* Move funds between accounts. *) (* TODO statement *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, sender_address, - reduce_sender_balance - |) in - do* modify_state (| + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| state, recipient_address, - increase_recipient_balance - |) in - + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. -Definition set_account_balance : M unit := +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := (* Sets the balance of an account. @@ -384,14 +397,14 @@ Definition set_account_balance : M unit := The amount that needs to set in balance. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - set_balance - |) in + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. - -Definition touch_account : M unit := +Definition touch_account (state : State) (address : Address) : M unit := (* Initializes an account to state. @@ -404,9 +417,9 @@ Definition touch_account : M unit := The address of the account that need to initialised. *) (* TODO statement *) + M.pure tt. - -Definition increment_nonce : M unit := +Definition increment_nonce (state : State) (address : Address) : M unit := (* Increments the nonce of an account. @@ -419,14 +432,14 @@ Definition increment_nonce : M unit := Address of the account whose nonce needs to be incremented. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_nonce - |) in + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. - -Definition set_code : M unit := +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := (* Sets Account code. @@ -442,14 +455,14 @@ Definition set_code : M unit := The bytecode that needs to be set. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - write_code - |) in - + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. -Definition create_ether : M unit := +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := (* Add newly created ether to an account. @@ -463,9 +476,9 @@ Definition create_ether : M unit := The amount of ether to be added to the account of interest. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_balance - |) in - + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. diff --git a/coq/ethereum/homestead/transactions.v b/coq/ethereum/homestead/transactions.v index 4811f98727..797f9426b7 100644 --- a/coq/ethereum/homestead/transactions.v +++ b/coq/ethereum/homestead/transactions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, @@ -9,4 +10,4 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require homestead.fork_types. +Require ethereum.homestead.fork_types. diff --git a/coq/ethereum/homestead/trie.v b/coq/ethereum/homestead/trie.v index 548de91e1c..6b8953f256 100644 --- a/coq/ethereum/homestead/trie.v +++ b/coq/ethereum/homestead/trie.v @@ -1,3 +1,4 @@ +(* Generated *) (* State Trie ^^^^^^^^^^ @@ -14,7 +15,7 @@ The state trie is the structure responsible for storing *) -Definition encode_internal_node : M unit := +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 @@ -35,22 +36,24 @@ Definition encode_internal_node : M unit := *) (* TODO statement *) (* TODO statement *) - let* encoded := rlp.["encode"] (| - unencoded - |) in + 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 : M unit := +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 : M unit := +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. @@ -66,9 +69,9 @@ Definition copy_trie : M unit := A copy of the trie. *) (* TODO statement *) + M.pure tt. - -Definition trie_set : M unit := +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := (* Stores an item in a Merkle Trie. @@ -85,9 +88,9 @@ Definition trie_set : M unit := Node to insert at `key`. *) (* TODO statement *) + M.pure tt. - -Definition trie_get : M unit := +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := (* Gets an item from the Merkle Trie. @@ -106,17 +109,17 @@ Definition trie_get : M unit := Node at `key` in the trie. *) (* TODO statement *) + M.pure tt. - -Definition common_prefix_length : M unit := +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 : M unit := +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := (* Compresses nibble-list into a standard byte array with a flag. @@ -150,14 +153,16 @@ Definition nibble_list_to_compact : M unit := compressed : `bytearray` Compact byte array. *) - let* compact := bytearray (| + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition bytes_to_nibble_list : M unit := +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := (* Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). @@ -171,14 +176,16 @@ Definition bytes_to_nibble_list : M unit := nibble_list : `Bytes` The `Bytes` in nibble-list format. *) - let* nibble_list := bytearray (| - (* TODO expression *) - |) in + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _prepare_trie : M unit := +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. @@ -199,9 +206,9 @@ Definition _prepare_trie : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition root : M unit := +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := (* Computes the root of a modified merkle patricia trie (MPT). @@ -219,22 +226,26 @@ Definition root : M unit := root : `.fork_types.Root` MPT root of the underlying key-value pairs. *) - let* obj := _prepare_trie (| - trie, - get_storage_root - |) in - let* root_node := encode_internal_node (| - patricialize (| - obj, - Uint (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) + M.pure tt. - -Definition patricialize : M unit := +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := (* Structural composition function. @@ -254,21 +265,29 @@ Definition patricialize : M unit := Root node of `obj`. *) (* TODO statement *) - let* arbitrary_key := next (| - iter (| - obj - |) - |) in + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in (* TODO statement *) - let* substring := (* TODO expression *) in - let* prefix_length := len (| - substring - |) in + 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 *) - let* value := (* TODO expression *) in + do* M.assign "value" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/homestead/utils/__init__.v b/coq/ethereum/homestead/utils/__init__.v index beff4482b1..7f30fe939b 100644 --- a/coq/ethereum/homestead/utils/__init__.v +++ b/coq/ethereum/homestead/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions unique to this particular fork. *) diff --git a/coq/ethereum/homestead/utils/address.v b/coq/ethereum/homestead/utils/address.v index 5399c03175..36fb655fbc 100644 --- a/coq/ethereum/homestead/utils/address.v +++ b/coq/ethereum/homestead/utils/address.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require homestead.fork_types. +Require ethereum.__init__. +Require ethereum.homestead.fork_types. -Definition to_address : M unit := +Definition to_address (data : (* TODO type *)) : M Address := (* Convert a Uint or U256 value to a valid address (20 bytes). @@ -33,9 +35,9 @@ Definition to_address : M unit := The obtained address. *) (* TODO statement *) + M.pure tt. - -Definition compute_contract_address : M unit := +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := (* Computes address of the new account that needs to be created. @@ -52,15 +54,21 @@ Definition compute_contract_address : M unit := address: `ethereum.homestead.fork_types.Address` The computed address of the new account. *) - let* computed_address := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *) - |) - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/homestead/utils/hexadecimal.v index eb2a313bdf..1c2f22a801 100644 --- a/coq/ethereum/homestead/utils/hexadecimal.v +++ b/coq/ethereum/homestead/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ types. *) Require ethereum.utils.hexadecimal. -Require homestead.fork_types. +Require ethereum.homestead.fork_types. -Definition hex_to_root : M unit := +Definition hex_to_root (hex_string : str) : M Root := (* Convert hex string to trie root. @@ -31,9 +32,9 @@ Definition hex_to_root : M unit := Trie root obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bloom : M unit := +Definition hex_to_bloom (hex_string : str) : M Bloom := (* Convert hex string to bloom. @@ -48,9 +49,9 @@ Definition hex_to_bloom : M unit := Bloom obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_address : M unit := +Definition hex_to_address (hex_string : str) : M Address := (* Convert hex string to Address (20 bytes). @@ -65,4 +66,4 @@ Definition hex_to_address : M unit := The address obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/homestead/utils/message.v b/coq/ethereum/homestead/utils/message.v index 557b041553..dbf5563f9b 100644 --- a/coq/ethereum/homestead/utils/message.v +++ b/coq/ethereum/homestead/utils/message.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For The Message Data-structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,12 +16,12 @@ Message specific functions used in this homestead version of specification. Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require homestead.fork_types. -Require homestead.state. -Require homestead.vm. -Require homestead.utils.address. +Require ethereum.homestead.fork_types. +Require ethereum.homestead.state. +Require ethereum.homestead.vm. +Require ethereum.homestead.utils.address. -Definition prepare_message : M unit := +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. @@ -52,4 +53,4 @@ Definition prepare_message : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/homestead/vm/__init__.v b/coq/ethereum/homestead/vm/__init__.v index e3cb8fad46..733993a8d3 100644 --- a/coq/ethereum/homestead/vm/__init__.v +++ b/coq/ethereum/homestead/vm/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,11 +19,11 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require homestead.blocks. -Require homestead.fork_types. -Require homestead.state. +Require ethereum.homestead.blocks. +Require ethereum.homestead.fork_types. +Require ethereum.homestead.state. -Definition incorporate_child_on_success : M unit := +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of a successful `child_evm` into the parent `evm`. @@ -33,15 +34,21 @@ Definition incorporate_child_on_success : M unit := child_evm : The child evm to incorporate. *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - do* evm.["accounts_to_delete"].["update"] (| - child_evm.["accounts_to_delete"] - |) in + 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 : M unit := +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. @@ -52,5 +59,7 @@ Definition incorporate_child_on_error : M unit := child_evm : The child evm to incorporate. *) - (* 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/homestead/vm/exceptions.v b/coq/ethereum/homestead/vm/exceptions.v index 1784494410..47e26555d5 100644 --- a/coq/ethereum/homestead/vm/exceptions.v +++ b/coq/ethereum/homestead/vm/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Exceptions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/homestead/vm/gas.v b/coq/ethereum/homestead/vm/gas.v index 96060b022b..555e3a9b77 100644 --- a/coq/ethereum/homestead/vm/gas.v +++ b/coq/ethereum/homestead/vm/gas.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Gas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,11 +18,12 @@ Require typing. Require ethereum_types.numeric. Require ethereum.trace. Require ethereum.utils.numeric. -Require homestead.fork_types. -Require homestead.state. -Require homestead.vm.exceptions. +Require ethereum.homestead.fork_types. +Require ethereum.homestead.state. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.exceptions. -Definition charge_gas : M unit := +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := (* Subtracts `amount` from `evm.gas_left`. @@ -33,18 +35,18 @@ Definition charge_gas : M unit := The amount of gas the current operation requires. *) - do* ethereum.trace.evm_trace (| + do* [[ ethereum.trace.evm_trace ~(| evm, - ethereum.trace.GasAndRefund (| - int (| + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| amount |) |) - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_memory_gas_cost : M unit := +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, @@ -60,14 +62,22 @@ Definition calculate_memory_gas_cost : M unit := total_gas_cost : `ethereum.base_types.Uint` The gas cost for storing data in memory. *) - let* size_in_words := (* TODO expression *) in - let* linear_cost := (* TODO expression *) in - let* quadratic_cost := (* TODO expression *) in - let* total_gas_cost := (* TODO expression *) in + 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 : M unit := +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := (* Calculates the gas amount to extend memory @@ -83,22 +93,28 @@ Definition calculate_gas_extend_memory : M unit := ------- extend_memory: `ExtendMemory` *) - let* size_to_extend := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* to_be_paid := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* current_size := ethereum_types.numeric.Uint (| - len (| - memory - |) - |) in + 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 : M unit := +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`. @@ -117,9 +133,17 @@ Definition calculate_message_call_gas : M unit := ------- message_call_gas: `MessageCallGas` *) - let* create_gas_cost := (* TODO expression *) in - let* transfer_gas_cost := (* TODO expression *) in - let* cost := (* TODO expression *) in - let* stipend := (* TODO expression *) in + 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__.v b/coq/ethereum/homestead/vm/instructions/__init__.v index b36b1ebfef..cbd7e7e63a 100644 --- a/coq/ethereum/homestead/vm/instructions/__init__.v +++ b/coq/ethereum/homestead/vm/instructions/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* EVM Instruction Encoding (Opcodes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/homestead/vm/instructions/arithmetic.v b/coq/ethereum/homestead/vm/instructions/arithmetic.v index 7e1cb83ac1..2bbaf77a26 100644 --- a/coq/ethereum/homestead/vm/instructions/arithmetic.v +++ b/coq/ethereum/homestead/vm/instructions/arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,11 @@ Implementations of the EVM Arithmetic instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require homestead.vm.gas. -Require homestead.vm.stack. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.stack. -Definition add : M unit := +Definition add (evm : Evm) : M unit := (* Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -28,27 +30,37 @@ Definition add : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_add"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sub (evm : Evm) : M unit := (* Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -59,27 +71,37 @@ Definition sub : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_sub"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mul (evm : Evm) : M unit := (* Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -90,27 +112,37 @@ Definition mul : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_mul"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition div (evm : Evm) : M unit := (* Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -121,25 +153,33 @@ Definition div : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |) in - let* divisor := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - quotient - |) 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 : M unit := +Definition sdiv (evm : Evm) : M unit := (* Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -150,31 +190,39 @@ Definition sdiv : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* divisor := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - quotient + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mod : M unit := +Definition mod (evm : Evm) : M unit := (* Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -185,25 +233,33 @@ Definition mod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - remainder - |) in + |) ]] 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 : M unit := +Definition smod (evm : Evm) : M unit := (* Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -214,31 +270,39 @@ Definition smod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* y := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - remainder + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition addmod : M unit := +Definition addmod (evm : Evm) : M unit := (* Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -249,34 +313,44 @@ Definition addmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +Definition mulmod (evm : Evm) : M unit := (* Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -287,34 +361,44 @@ Definition mulmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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 : M unit := +Definition exp (evm : Evm) : M unit := (* Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -325,39 +409,53 @@ Definition exp : M unit := The current EVM frame. *) - let* base := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent_bits := exponent.["bit_length"] (| - - |) in - let* exponent_bytes := (* TODO expression *) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - pow (| - base, - exponent, - (* 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 - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition signextend : M unit := +Definition signextend (evm : Evm) : M unit := (* Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -368,20 +466,28 @@ Definition signextend : M unit := The current EVM frame. *) - let* byte_num := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/homestead/vm/instructions/bitwise.v index 6de26bb822..8682c0544e 100644 --- a/coq/ethereum/homestead/vm/instructions/bitwise.v +++ b/coq/ethereum/homestead/vm/instructions/bitwise.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Bitwise Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM bitwise instructions. *) Require ethereum_types.numeric. -Require homestead.vm.gas. -Require homestead.vm.stack. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.stack. -Definition bitwise_and : M unit := +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. @@ -27,24 +29,32 @@ Definition bitwise_and : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_or : M unit := + |) ]] 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. @@ -55,24 +65,32 @@ Definition bitwise_or : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_xor : M unit := + |) ]] 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. @@ -83,24 +101,32 @@ Definition bitwise_xor : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_not : M unit := + |) ]] 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. @@ -111,21 +137,27 @@ Definition bitwise_not : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition get_byte : M unit := + |) ]] 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 @@ -137,20 +169,28 @@ Definition get_byte : M unit := The current EVM frame. *) - let* byte_index := stack.pop (| - evm.["stack"] - |) in - let* word := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/homestead/vm/instructions/block.v index 2c8581802b..13153fbbcf 100644 --- a/coq/ethereum/homestead/vm/instructions/block.v +++ b/coq/ethereum/homestead/vm/instructions/block.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Block Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM block instructions. *) Require ethereum_types.numeric. -Require homestead.vm.gas. -Require homestead.vm.stack. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.stack. -Definition block_hash : M unit := +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. @@ -27,27 +29,35 @@ Definition block_hash : M unit := The current EVM frame. *) - let* block_number := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* max_block_number := (* TODO expression *) in + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition coinbase : M unit := +Definition coinbase (evm : Evm) : M unit := (* Push the current block's beneficiary address (address of the block miner) onto the stack. @@ -62,20 +72,24 @@ Definition coinbase : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["coinbase"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition timestamp : M unit := +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. @@ -90,18 +104,22 @@ Definition timestamp : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["env"].["time"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition number (evm : Evm) : M unit := (* Push the current block's number onto the stack. @@ -115,20 +133,24 @@ Definition number : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["number"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition difficulty : M unit := +Definition difficulty (evm : Evm) : M unit := (* Push the current block's difficulty onto the stack. @@ -142,20 +164,24 @@ Definition difficulty : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["difficulty"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_limit : M unit := +Definition gas_limit (evm : Evm) : M unit := (* Push the current block's gas limit onto the stack. @@ -169,15 +195,19 @@ Definition gas_limit : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_limit"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/homestead/vm/instructions/comparison.v index 3c0d9e716a..072b6a631f 100644 --- a/coq/ethereum/homestead/vm/instructions/comparison.v +++ b/coq/ethereum/homestead/vm/instructions/comparison.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Comparison Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM Comparison instructions. *) Require ethereum_types.numeric. -Require homestead.vm.gas. -Require homestead.vm.stack. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.stack. -Definition less_than : M unit := +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. @@ -27,27 +29,37 @@ Definition less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_less_than : M unit := + |) ]] 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. @@ -57,31 +69,41 @@ Definition signed_less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition greater_than : M unit := + |) ]] 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. @@ -92,27 +114,37 @@ Definition greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_greater_than : M unit := + |) ]] 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. @@ -122,31 +154,41 @@ Definition signed_greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition equal : M unit := + |) ]] 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. @@ -157,27 +199,37 @@ Definition equal : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition is_zero : M unit := + |) ]] 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. @@ -188,19 +240,27 @@ Definition is_zero : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/homestead/vm/instructions/control_flow.v index 8559f589ea..77e0597fd7 100644 --- a/coq/ethereum/homestead/vm/instructions/control_flow.v +++ b/coq/ethereum/homestead/vm/instructions/control_flow.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Control Flow Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM control flow instructions. *) Require ethereum_types.numeric. -Require homestead.vm.gas. -Require homestead.vm.exceptions. -Require homestead.vm.stack. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.exceptions. +Require ethereum.homestead.vm.stack. -Definition stop : M unit := +Definition stop (evm : Evm) : M unit := (* Stop further execution of EVM code. @@ -29,10 +31,14 @@ Definition stop : M unit := (* TODO statement *) (* TODO statement *) (* TODO assignment *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jump : M unit := +Definition jump (evm : Evm) : M unit := (* Alter the program counter to the location specified by the top of the stack. @@ -43,20 +49,22 @@ Definition jump : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition jumpi : M unit := +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 @@ -68,23 +76,27 @@ Definition jumpi : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* conditional_value := stack.pop (| - evm.["stack"] - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition pc : M unit := +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. @@ -96,20 +108,24 @@ Definition pc : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["pc"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_left : M unit := +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. @@ -121,20 +137,24 @@ Definition gas_left : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["gas_left"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jumpdest : M unit := +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 @@ -147,10 +167,14 @@ Definition jumpdest : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_JUMPDEST - |) in - (* TODO statement *) + |) ]] 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.v b/coq/ethereum/homestead/vm/instructions/environment.v index b831ae9a31..ea707d042c 100644 --- a/coq/ethereum/homestead/vm/instructions/environment.v +++ b/coq/ethereum/homestead/vm/instructions/environment.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,13 +15,14 @@ Implementations of the EVM environment related instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require homestead.state. -Require homestead.utils.address. -Require homestead.vm.memory. -Require homestead.vm.gas. -Require homestead.vm.stack. - -Definition address : M unit := +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. @@ -31,20 +33,24 @@ Definition address : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["current_target"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition balance : M unit := +Definition balance (evm : Evm) : M unit := (* Pushes the balance of the given account onto the stack. @@ -54,27 +60,35 @@ Definition balance : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* balance := state.get_account (| - evm.["env"].["state"], - address - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +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. @@ -86,20 +100,24 @@ Definition origin : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["origin"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition caller : M unit := +Definition caller (evm : Evm) : M unit := (* Pushes the address of the caller onto the stack. @@ -110,20 +128,24 @@ Definition caller : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["caller"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition callvalue : M unit := +Definition callvalue (evm : Evm) : M unit := (* Push the value (in wei) sent with the call onto the stack. @@ -134,18 +156,22 @@ Definition callvalue : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["message"].["value"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition calldataload (evm : Evm) : M unit := (* Push a word (32 bytes) of the input data belonging to the current environment onto the stack. @@ -156,30 +182,38 @@ Definition calldataload : M unit := The current EVM frame. *) - let* start_index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - start_index, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] 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* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - value + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 |) - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition calldatasize : M unit := +Definition calldatasize (evm : Evm) : M unit := (* Push the size of input data in current environment onto the stack. @@ -190,22 +224,26 @@ Definition calldatasize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["message"].["data"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition calldatacopy : M unit := +Definition calldatacopy (evm : Evm) : M unit := (* Copy a portion of the input data in current environment to memory. @@ -218,40 +256,60 @@ Definition calldatacopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* data_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - data_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition codesize (evm : Evm) : M unit := (* Push the size of code running in current environment onto the stack. @@ -262,22 +320,26 @@ Definition codesize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["code"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition codecopy : M unit := +Definition codecopy (evm : Evm) : M unit := (* Copy a portion of the code in current environment to memory. @@ -290,40 +352,60 @@ Definition codecopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["code"], - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition gasprice (evm : Evm) : M unit := (* Push the gas price used in current environment onto the stack. @@ -334,20 +416,24 @@ Definition gasprice : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_price"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition extcodesize : M unit := +Definition extcodesize (evm : Evm) : M unit := (* Push the code size of a given account onto the stack. @@ -357,31 +443,39 @@ Definition extcodesize : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* codesize := ethereum_types.numeric.U256 (| - len (| - state.get_account (| - evm.["env"].["state"], - address - |).["code"] + |) ]] 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 - do* stack.push (| - evm.["stack"], - codesize - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition extcodecopy : M unit := +Definition extcodecopy (evm : Evm) : M unit := (* Copy a portion of an account's code to memory. @@ -391,44 +485,68 @@ Definition extcodecopy : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* code := state.get_account (| - evm.["env"].["state"], - address - |).["code"] in - let* value := vm.memory.buffer_read (| - code, - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/homestead/vm/instructions/keccak.v index 593b441512..577c4f3b50 100644 --- a/coq/ethereum/homestead/vm/instructions/keccak.v +++ b/coq/ethereum/homestead/vm/instructions/keccak.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Keccak Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM keccak instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require homestead.vm.gas. -Require homestead.vm.memory. -Require homestead.vm.stack. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.memory. +Require ethereum.homestead.vm.stack. -Definition keccak : M unit := +Definition keccak (evm : Evm) : M unit := (* Pushes to the stack the Keccak-256 hash of a region of memory. @@ -32,36 +34,56 @@ Definition keccak : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* word_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in - let* hash := ethereum.crypto.hash.keccak256 (| - data - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/homestead/vm/instructions/log.v index 9da37966ec..92657d71fa 100644 --- a/coq/ethereum/homestead/vm/instructions/log.v +++ b/coq/ethereum/homestead/vm/instructions/log.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Logging Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,12 +15,13 @@ Implementations of the EVM logging instructions. Require functools. Require ethereum_types.numeric. -Require homestead.blocks. -Require homestead.vm.gas. -Require homestead.vm.memory. -Require homestead.vm.stack. +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 : M unit := +Definition log_n (evm : Evm) (num_topics : U256) : M unit := (* Appends a log entry, having `num_topics` topics, to the evm logs. @@ -34,26 +36,42 @@ Definition log_n : M unit := The number of topics to be included in the log entry. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* topics := (* TODO expression *) in + 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 *) - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - let* log_entry := blocks.Log (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "log_entry" [[ + blocks.Log ~(| - |) in + |) in + ]] in (* TODO assignment *) - (* 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/memory.v b/coq/ethereum/homestead/vm/instructions/memory.v index 1140586852..c5a4e7abe3 100644 --- a/coq/ethereum/homestead/vm/instructions/memory.v +++ b/coq/ethereum/homestead/vm/instructions/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM Memory instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require homestead.vm.gas. -Require homestead.vm.memory. -Require homestead.vm.stack. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.memory. +Require ethereum.homestead.vm.stack. -Definition mstore : M unit := +Definition mstore (evm : Evm) : M unit := (* Stores a word to memory. This also expands the memory, if the memory is @@ -30,32 +32,44 @@ Definition mstore : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* memory.memory_write (| - evm.["memory"], - start_position, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mstore8 (evm : Evm) : M unit := (* Stores a byte to memory. This also expands the memory, if the memory is @@ -67,33 +81,47 @@ Definition mstore8 : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ (* TODO expression *) - |) in - do* memory.memory_write (| - evm.["memory"], - start_position, - normalized_bytes_value - |) in - (* TODO statement *) - + ]] 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 : M unit := +Definition mload (evm : Evm) : M unit := (* Load word from memory. @@ -103,35 +131,47 @@ Definition mload : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.memory_read_bytes (| - evm.["memory"], - start_position, - ethereum_types.numeric.U256 (| - (* 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 - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition msize : M unit := +Definition msize (evm : Evm) : M unit := (* Push the size of active memory in bytes onto the stack. @@ -142,17 +182,21 @@ Definition msize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["memory"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/homestead/vm/instructions/stack.v index e73a536f4a..e5a9c2d19c 100644 --- a/coq/ethereum/homestead/vm/instructions/stack.v +++ b/coq/ethereum/homestead/vm/instructions/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM stack related instructions. Require functools. Require ethereum_types.numeric. -Require homestead.vm.exceptions. -Require homestead.vm.gas. -Require homestead.vm.memory. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.exceptions. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.memory. -Definition pop : M unit := +Definition pop (evm : Evm) : M unit := (* Remove item from stack. @@ -28,18 +30,22 @@ Definition pop : M unit := The current EVM frame. *) - do* stack.["pop"] (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in + |) ]] in (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition push_n : M unit := +Definition push_n (evm : Evm) (num_bytes : int) : M unit := (* Pushes a N-byte immediate onto the stack. @@ -54,29 +60,33 @@ Definition push_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - evm.["code"], - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - num_bytes + |) ]] 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 - do* stack.["push"] (| - evm.["stack"], - data_to_push - |) in - (* TODO statement *) - - -Definition dup_n : M unit := + |) 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. @@ -91,20 +101,26 @@ Definition dup_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - let* data_to_duplicate := (* TODO expression *) in - do* stack.["push"] (| - evm.["stack"], - data_to_duplicate - |) 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 : M unit := +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. @@ -123,11 +139,15 @@ Definition swap_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - (* 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/storage.v b/coq/ethereum/homestead/vm/instructions/storage.v index dc3f8939a6..d5370c8953 100644 --- a/coq/ethereum/homestead/vm/instructions/storage.v +++ b/coq/ethereum/homestead/vm/instructions/storage.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Storage Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM storage related instructions. *) Require ethereum_types.numeric. -Require homestead.state. -Require homestead.vm.gas. -Require homestead.vm.stack. +Require ethereum.homestead.state. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.stack. -Definition sload : M unit := +Definition sload (evm : Evm) : M unit := (* Loads to the stack, the value corresponding to a certain key from the storage of the current account. @@ -28,28 +30,36 @@ Definition sload : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_SLOAD - |) in - let* value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sstore (evm : Evm) : M unit := (* Stores a value at a certain key in the current context's storage. @@ -59,30 +69,40 @@ Definition sstore : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in - let* current_value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in + |) 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - do* state.set_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key, - new_value - |) in - (* TODO statement *) - + 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.v b/coq/ethereum/homestead/vm/instructions/system.v index 71d4317017..4759fcae3c 100644 --- a/coq/ethereum/homestead/vm/instructions/system.v +++ b/coq/ethereum/homestead/vm/instructions/system.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) System Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,14 +15,15 @@ Implementations of the EVM system related instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require homestead.fork_types. -Require homestead.state. -Require homestead.utils.address. -Require homestead.vm.gas. -Require homestead.vm.memory. -Require homestead.vm.stack. +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 : M unit := +Definition create (evm : Evm) : M unit := (* Creates a new account with associated code. @@ -31,43 +33,65 @@ Definition create : M unit := The current EVM frame. *) (* TODO statement *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - let* create_message_gas := evm.["gas_left"] in + |) ]] 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 *) - let* sender_address := evm.["message"].["current_target"] in - let* sender := state.get_account (| - evm.["env"].["state"], - sender_address - |) in - let* contract_address := utils.address.compute_contract_address (| - evm.["message"].["current_target"], - state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["nonce"] - |) in - (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition return_ : M unit := +Definition return_ (evm : Evm) : M unit := (* Halts execution returning output data. @@ -76,65 +100,83 @@ Definition return_ : M unit := evm : The current EVM frame. *) - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) + |) ]] 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 : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_input_start_position, - memory_input_size - |) in - let* code := state.get_account (| - evm.["env"].["state"], - code_address - |).["code"] in - let* child_message := Message (| + 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 - let* child_evm := process_message (| - child_message, - evm.["env"] - |) in + |) 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 *) - let* actual_output_size := min (| - memory_output_size, - ethereum_types.numeric.U256 (| - len (| - child_evm.["output"] + 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 - do* memory.memory_write (| - evm.["memory"], + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), memory_output_start_position, (* TODO expression *) - |) in + |) ]] in + M.pure tt. - -Definition call : M unit := +Definition call (evm : Evm) : M unit := (* Message-call into an account. @@ -143,55 +185,81 @@ Definition call : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* message_call_gas := gas.calculate_message_call_gas (| - evm.["env"].["state"], - gas, - to, - value - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition callcode (evm : Evm) : M unit := (* Message-call into this account with alternative account’s code. @@ -200,56 +268,84 @@ Definition callcode : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* to := evm.["message"].["current_target"] in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* message_call_gas := gas.calculate_message_call_gas (| - evm.["env"].["state"], - gas, - to, - value - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition selfdestruct (evm : Evm) : M unit := (* Halt execution and register account for later deletion. @@ -258,49 +354,63 @@ Definition selfdestruct : M unit := evm : The current EVM frame. *) - let* beneficiary := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* gas_cost := gas.GAS_ZERO in - let* originator := evm.["message"].["current_target"] in - let* refunded_accounts := evm.["accounts_to_delete"] in - let* parent_evm := evm.["message"].["parent_evm"] in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - let* beneficiary_balance := state.get_account (| - evm.["env"].["state"], - beneficiary - |).["balance"] in - let* originator_balance := state.get_account (| - evm.["env"].["state"], - originator - |).["balance"] in - do* state.set_account_balance (| - evm.["env"].["state"], - beneficiary, + 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 (| - evm.["env"].["state"], - originator, - ethereum_types.numeric.U256 (| - (* 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* evm.["accounts_to_delete"].["add"] (| - originator - |) in + |) ]] 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 : M unit := +Definition delegatecall (evm : Evm) : M unit := (* Message-call into an account. @@ -309,49 +419,69 @@ Definition delegatecall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - gas, - evm.["message"].["value"], - evm.["message"].["caller"], - evm.["message"].["current_target"], - code_address, - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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.v b/coq/ethereum/homestead/vm/interpreter.v index fc1c693a21..7ca9baf48e 100644 --- a/coq/ethereum/homestead/vm/interpreter.v +++ b/coq/ethereum/homestead/vm/interpreter.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Interpreter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +18,18 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.trace. -Require homestead.blocks. -Require homestead.fork_types. -Require homestead.state. -Require homestead.vm. -Require homestead.vm.gas. -Require homestead.vm.precompiled_contracts.mapping. -Require homestead.vm.exceptions. -Require homestead.vm.instructions. -Require homestead.vm.runtime. - -Definition process_message_call : M unit := +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`. @@ -47,19 +49,21 @@ Definition process_message_call : M unit := *) (* TODO statement *) (* TODO statement *) - let* tx_end := ethereum.trace.TransactionEnd (| - (* TODO expression *), - evm.["output"], - evm.["error"] - |) in - do* ethereum.trace.evm_trace (| - evm, - tx_end - |) in + 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 : M unit := +Definition process_create_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -75,22 +79,24 @@ Definition process_create_message : M unit := evm: :py:class:`~ethereum.homestead.vm.Evm` Items containing execution specific objects. *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.destroy_storage (| - env.["state"], - message.["current_target"] - |) in - let* evm := process_message (| - message, - env - |) in + 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 : M unit := +Definition process_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -107,23 +113,25 @@ Definition process_message : M unit := Items containing execution specific objects *) (* TODO statement *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.touch_account (| - env.["state"], - message.["current_target"] - |) in + 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 *) - let* evm := execute_code (| - message, - env - |) in + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition execute_code : M unit := +Definition execute_code (message : Message) (env : Environment) : M Evm := (* Executes bytecode present in the `message`. @@ -139,13 +147,19 @@ Definition execute_code : M unit := evm: `ethereum.vm.EVM` Items containing execution specific objects *) - let* code := message.["code"] in - let* valid_jump_destinations := runtime.get_valid_jump_destinations (| - code - |) in - let* evm := Evm (| - - |) in + 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.v b/coq/ethereum/homestead/vm/memory.v index 94b6a44639..88b516318f 100644 --- a/coq/ethereum/homestead/vm/memory.v +++ b/coq/ethereum/homestead/vm/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.byte. -Definition memory_write : M unit := +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := (* Writes to memory. @@ -30,9 +31,9 @@ Definition memory_write : M unit := Data to write to memory. *) (* TODO assignment *) + M.pure tt. - -Definition memory_read_bytes : M unit := +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := (* Read bytes from memory. @@ -51,9 +52,9 @@ Definition memory_read_bytes : M unit := Data read from memory. *) (* TODO statement *) + M.pure tt. - -Definition buffer_read : M unit := +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := (* Read bytes from a buffer. Padding with zeros if necessary. @@ -72,4 +73,4 @@ Definition buffer_read : M unit := Data read from memory. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/homestead/vm/precompiled_contracts/__init__.v b/coq/ethereum/homestead/vm/precompiled_contracts/__init__.v index 88d5fdef55..2a101b8e64 100644 --- a/coq/ethereum/homestead/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/homestead/vm/precompiled_contracts/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,4 +14,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require homestead.utils.hexadecimal. +Require ethereum.homestead.utils.hexadecimal. diff --git a/coq/ethereum/homestead/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/homestead/vm/precompiled_contracts/ecrecover.v index 546095c1ec..7da8669e4f 100644 --- a/coq/ethereum/homestead/vm/precompiled_contracts/ecrecover.v +++ b/coq/ethereum/homestead/vm/precompiled_contracts/ecrecover.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,11 +17,11 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require homestead.vm. -Require homestead.vm.gas. -Require homestead.vm.memory. +Require ethereum.homestead.vm. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.memory. -Definition ecrecover : M unit := +Definition ecrecover (evm : Evm) : M unit := (* Decrypts the address using elliptic curve DSA recovery mechanism and writes the address to output. @@ -30,64 +31,80 @@ Definition ecrecover : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* message_hash_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* message_hash := ethereum.crypto.hash.Hash32 (| - message_hash_bytes - |) in - let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + ethereum_types.numeric.U256 ~(| + 32 |) - |) - |) in - let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 + ]] 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 *) - let* address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/homestead/vm/precompiled_contracts/identity.v index 92e3c9c09d..2a556b5d08 100644 --- a/coq/ethereum/homestead/vm/precompiled_contracts/identity.v +++ b/coq/ethereum/homestead/vm/precompiled_contracts/identity.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,10 @@ Implementation of the `IDENTITY` precompiled contract. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require homestead.vm. -Require homestead.vm.gas. +Require ethereum.homestead.vm. +Require ethereum.homestead.vm.gas. -Definition identity : M unit := +Definition identity (evm : Evm) : M unit := (* Writes the message data to output. @@ -26,11 +27,15 @@ Definition identity : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/homestead/vm/precompiled_contracts/mapping.v b/coq/ethereum/homestead/vm/precompiled_contracts/mapping.v index 66be2c3300..82ffcb5b5a 100644 --- a/coq/ethereum/homestead/vm/precompiled_contracts/mapping.v +++ b/coq/ethereum/homestead/vm/precompiled_contracts/mapping.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,8 +14,9 @@ Mapping of precompiled contracts their implementations. *) Require typing. -Require homestead.fork_types. -Require homestead.vm.precompiled_contracts.ecrecover. -Require homestead.vm.precompiled_contracts.identity. -Require homestead.vm.precompiled_contracts.ripemd160. -Require homestead.vm.precompiled_contracts.sha256. +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.v b/coq/ethereum/homestead/vm/precompiled_contracts/ripemd160.v index bc5e73dd3c..fe2c66bbe6 100644 --- a/coq/ethereum/homestead/vm/precompiled_contracts/ripemd160.v +++ b/coq/ethereum/homestead/vm/precompiled_contracts/ripemd160.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `RIPEMD160` precompiled contract. *) -Definition ripemd160 : M unit := +Definition ripemd160 (evm : Evm) : M unit := (* Writes the ripemd160 hash to output. @@ -22,21 +23,29 @@ Definition ripemd160 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 - let* hash_bytes := hashlib.["new"] (| - (* TODO expression *), - data - |).["digest"] (| - - |) in - let* padded_hash := left_pad_zero_bytes (| - hash_bytes, - (* TODO expression *) - |) in + |) ]] 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.v b/coq/ethereum/homestead/vm/precompiled_contracts/sha256.v index da6972d411..3ba3ffe7aa 100644 --- a/coq/ethereum/homestead/vm/precompiled_contracts/sha256.v +++ b/coq/ethereum/homestead/vm/precompiled_contracts/sha256.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `SHA256` precompiled contract. *) -Definition sha256 : M unit := +Definition sha256 (evm : Evm) : M unit := (* Writes the sha256 hash to output. @@ -22,11 +23,15 @@ Definition sha256 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/homestead/vm/runtime.v b/coq/ethereum/homestead/vm/runtime.v index 422aa6768f..9810c1185c 100644 --- a/coq/ethereum/homestead/vm/runtime.v +++ b/coq/ethereum/homestead/vm/runtime.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Runtime Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Runtime related operations used while executing EVM code. Require typing. Require ethereum_types.numeric. -Require homestead.vm.instructions. +Require ethereum.homestead.vm.instructions. -Definition get_valid_jump_destinations : M unit := +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := (* Analyze the evm code to obtain the set of valid jump destinations. @@ -38,12 +39,16 @@ Definition get_valid_jump_destinations : M unit := valid_jump_destinations: `Set[Uint]` The set of valid jump destinations in the code. *) - let* valid_jump_destinations := set (| - - |) in - let* pc := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/homestead/vm/stack.v index 8ecce81148..07328e37af 100644 --- a/coq/ethereum/homestead/vm/stack.v +++ b/coq/ethereum/homestead/vm/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Implementation of the stack operators for the EVM. Require typing. Require ethereum_types.numeric. -Require homestead.vm.exceptions. +Require ethereum.homestead.vm.exceptions. -Definition pop : M unit := +Definition pop (stack : (* TODO type *)) : M U256 := (* Pops the top item off of `stack`. @@ -33,9 +34,9 @@ Definition pop : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition push : M unit := +Definition push (stack : (* TODO type *)) (value : U256) : M unit := (* Pushes `value` onto `stack`. @@ -50,4 +51,4 @@ Definition push : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/istanbul/__init__.v b/coq/ethereum/istanbul/__init__.v index 707b65b3e7..87e3cb056d 100644 --- a/coq/ethereum/istanbul/__init__.v +++ b/coq/ethereum/istanbul/__init__.v @@ -1,3 +1,4 @@ +(* 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 diff --git a/coq/ethereum/istanbul/blocks.v b/coq/ethereum/istanbul/blocks.v index d31caca2a8..317be6c28f 100644 --- a/coq/ethereum/istanbul/blocks.v +++ b/coq/ethereum/istanbul/blocks.v @@ -1,3 +1,4 @@ +(* 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 @@ -14,6 +15,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. -Require istanbul.fork_types. -Require istanbul.transactions. +Require ethereum.crypto.hash. +Require ethereum.istanbul.fork_types. +Require ethereum.istanbul.transactions. diff --git a/coq/ethereum/istanbul/bloom.v b/coq/ethereum/istanbul/bloom.v index 6daec8e931..28d3227f1a 100644 --- a/coq/ethereum/istanbul/bloom.v +++ b/coq/ethereum/istanbul/bloom.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Logs Bloom ^^^^^^^^^^^^^^^^^^^ @@ -19,10 +20,10 @@ eliminating blocks and receipts from their search. Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require istanbul.blocks. -Require istanbul.fork_types. +Require ethereum.istanbul.blocks. +Require ethereum.istanbul.fork_types. -Definition add_to_bloom : M unit := +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := (* Add a bloom entry to the bloom filter (`bloom`). @@ -37,13 +38,15 @@ Definition add_to_bloom : M unit := bloom_entry : An entry which is to be added to bloom filter. *) - let* hash := ethereum.crypto.hash.keccak256 (| - bloom_entry - |) in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition logs_bloom : M unit := +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := (* Obtain the logs bloom from a list of log entries. @@ -63,4 +66,4 @@ Definition logs_bloom : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/istanbul/fork.v b/coq/ethereum/istanbul/fork.v index 7cede29ef6..a315352ef1 100644 --- a/coq/ethereum/istanbul/fork.v +++ b/coq/ethereum/istanbul/fork.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^ @@ -20,16 +21,18 @@ Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.ethash. Require ethereum.exceptions. -Require istanbul.blocks. -Require istanbul.bloom. -Require istanbul.fork_types. -Require istanbul.state. -Require istanbul.transactions. -Require istanbul.trie. -Require istanbul.utils.message. -Require istanbul.vm.interpreter. - -Definition apply_fork : M unit := +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. @@ -49,9 +52,9 @@ Definition apply_fork : M unit := Upgraded block chain object for this hard fork. *) (* TODO statement *) + M.pure tt. - -Definition get_last_256_block_hashes : M unit := +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. @@ -71,22 +74,28 @@ Definition get_last_256_block_hashes : M unit := recent_block_hashes : `List[Hash32]` Hashes of the recent 256 blocks in order of increasing block number. *) - let* recent_blocks := (* TODO expression *) in - (* TODO statement *) - let* recent_block_hashes := (* TODO expression *) in - (* TODO statement *) - let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *).["header"] - |) - |) in - do* recent_block_hashes.["append"] (| - most_recent_block_hash - |) in - (* TODO statement *) - - -Definition state_transition : M unit := + 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. @@ -108,42 +117,46 @@ Definition state_transition : M unit := block : Block to apply to `chain`. *) - let* parent_header := (* TODO expression *).["header"] in - do* validate_header (| - block.["header"], - parent_header - |) in - do* validate_ommers (| - block.["ommers"], - block.["header"], + 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 - let* apply_body_output := apply_body (| - chain.["state"], - get_last_256_block_hashes (| - chain - |), - block.["header"].["coinbase"], - block.["header"].["number"], - block.["header"].["gas_limit"], - block.["header"].["timestamp"], - block.["header"].["difficulty"], - block.["transactions"], - block.["ommers"], - chain.["chain_id"] - |) in + |) ]] 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* chain.["blocks"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| block - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition validate_header : M unit := +Definition validate_header (header : Header) (parent_header : Header) : M unit := (* Verifies a block header. @@ -161,31 +174,37 @@ Definition validate_header : M unit := parent_header : Parent Header of the header to check for correctness *) - let* parent_has_ommers := (* TODO expression *) in + do* M.assign "parent_has_ommers" [[ + (* TODO expression *) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* block_difficulty := calculate_block_difficulty (| - header.["number"], - header.["timestamp"], - parent_header.["timestamp"], - parent_header.["difficulty"], - parent_has_ommers - |) in + 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 *) - let* block_parent_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - parent_header - |) - |) in + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in (* TODO statement *) - do* validate_proof_of_work (| + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| header - |) in - + |) ]] in + M.pure tt. -Definition generate_header_hash_for_pow : M unit := +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. @@ -208,11 +227,13 @@ Definition generate_header_hash_for_pow : M unit := hash : `Hash32` The PoW valid rlp hash of the passed in header. *) - let* header_data_without_pow_artefacts := (* TODO expression *) in + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition validate_proof_of_work : M unit := +Definition validate_proof_of_work (header : Header) : M unit := (* Validates the Proof of Work constraints. @@ -227,19 +248,25 @@ Definition validate_proof_of_work : M unit := header : Header of interest. *) - let* header_hash := generate_header_hash_for_pow (| - header - |) in - let* cache := ethereum.ethash.generate_cache (| - header.["number"] - |) in + 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 *) - let* limit := (* TODO expression *) in + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition check_transaction : M unit := +Definition check_transaction (tx : Transaction) (gas_available : Uint) (chain_id : U64) : M Address := (* Check if the transaction is includable in the block. @@ -263,14 +290,16 @@ Definition check_transaction : M unit := If the transaction is not includable. *) (* TODO statement *) - let* sender_address := recover_sender (| - chain_id, - tx - |) in + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition make_receipt : M unit := +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. @@ -291,13 +320,15 @@ Definition make_receipt : M unit := receipt : The receipt for the transaction. *) - let* receipt := blocks.Receipt (| + do* M.assign "receipt" [[ + blocks.Receipt ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition apply_body : M unit := +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. @@ -338,25 +369,31 @@ Definition apply_body : M unit := apply_body_output : `ApplyBodyOutput` Output of applying the block body to the state. *) - let* gas_available := block_gas_limit in + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - do* pay_rewards (| + do* [[ M.get_local ~(| "pay_rewards" |) ~(| state, block_number, coinbase, ommers - |) in - let* block_gas_used := (* TODO expression *) in - let* block_logs_bloom := bloom.logs_bloom (| - block_logs - |) in - (* TODO statement *) - - -Definition validate_ommers : M unit := + |) ]] 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. @@ -378,23 +415,31 @@ Definition validate_ommers : M unit := chain : History and current state. *) - let* block_hash := rlp.["rlp_hash"] (| - block_header - |) in + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* ommers_hashes := (* TODO expression *) in + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* recent_canonical_blocks := (* TODO expression *) in - let* recent_canonical_block_hashes := (* TODO expression *) in + 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 : M unit := +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. @@ -420,21 +465,25 @@ Definition pay_rewards : M unit := ommers : List of ommers mentioned in the current block. *) - let* ommer_count := ethereum_types.numeric.U256 (| - len (| - ommers - |) - |) in - let* miner_reward := (* TODO expression *) in - do* state.create_ether (| + 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, - miner_reward - |) in + M.get_local ~(| "miner_reward" |) + |) ]] in (* TODO statement *) + M.pure tt. - -Definition process_transaction : M unit := +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := (* Execute a transaction against the provided environment. @@ -462,64 +511,92 @@ Definition process_transaction : M unit := Logs generated during execution. *) (* TODO statement *) - let* sender := env.["origin"] in - let* sender_account := state.get_account (| - env.["state"], - sender - |) in - let* gas_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* gas := (* TODO expression *) in - do* state.increment_nonce (| - env.["state"], - sender - |) in - let* sender_balance_after_gas_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - ethereum_types.numeric.U256 (| - sender_balance_after_gas_fee - |) - |) in - let* message := utils.message.prepare_message (| - sender, - tx.["to"], - tx.["value"], - tx.["data"], - gas, - env - |) in - let* output := vm.interpreter.process_message_call (| - message, - env - |) in - let* gas_used := (* TODO expression *) in - let* gas_refund := min (| - (* TODO expression *), - ethereum_types.numeric.Uint (| - output.["refund_counter"] + 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 - let* gas_refund_amount := (* TODO expression *) in - let* transaction_fee := (* TODO expression *) in - let* total_gas_used := (* TODO expression *) in - let* sender_balance_after_refund := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - sender_balance_after_refund - |) in - let* coinbase_balance_after_mining_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - - -Definition validate_transaction : M unit := + |) ]] 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. @@ -547,9 +624,9 @@ Definition validate_transaction : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition calculate_intrinsic_cost : M unit := +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := (* Calculates the gas that is charged before execution is started. @@ -572,13 +649,15 @@ Definition calculate_intrinsic_cost : M unit := verified : `ethereum.base_types.Uint` The intrinsic cost of the transaction. *) - let* data_cost := (* TODO expression *) in + do* M.assign "data_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition recover_sender : M unit := +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := (* Extracts the sender address from a transaction. @@ -605,9 +684,9 @@ Definition recover_sender : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_pre155 : M unit := +Definition signing_hash_pre155 (tx : Transaction) : M Hash32 := (* Compute the hash of a transaction used in a legacy (pre EIP 155) signature. @@ -622,9 +701,9 @@ Definition signing_hash_pre155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_155 : M unit := +Definition signing_hash_155 (tx : Transaction) (chain_id : U64) : M Hash32 := (* Compute the hash of a transaction used in a EIP 155 signature. @@ -641,9 +720,9 @@ Definition signing_hash_155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition compute_header_hash : M unit := +Definition compute_header_hash (header : Header) : M Hash32 := (* Computes the hash of a block header. @@ -676,9 +755,9 @@ Definition compute_header_hash : M unit := Hash of the header. *) (* TODO statement *) + M.pure tt. - -Definition check_gas_limit : M unit := +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := (* Validates the gas limit for a block. @@ -706,14 +785,16 @@ Definition check_gas_limit : M unit := check : `bool` True if gas limit constraints are satisfied, False otherwise. *) - let* max_adjustment_delta := (* TODO expression *) in + 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 : M unit := +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. @@ -752,9 +833,15 @@ Definition calculate_block_difficulty : M unit := difficulty : `ethereum.base_types.Uint` Computed difficulty for a block. *) - let* offset := (* TODO expression *) in - let* difficulty := (* TODO expression *) in - let* num_bomb_periods := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - + 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.v b/coq/ethereum/istanbul/fork_types.v index 14de99d5e5..d84cffdf45 100644 --- a/coq/ethereum/istanbul/fork_types.v +++ b/coq/ethereum/istanbul/fork_types.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Types ^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. +Require ethereum.__init__. +Require ethereum.crypto.hash. -Definition encode_account : M unit := +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := (* Encode `Account` dataclass. @@ -26,4 +28,4 @@ Definition encode_account : M unit := encoded without providing a storage root. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/istanbul/state.v b/coq/ethereum/istanbul/state.v index 11071bec95..ba5f792df9 100644 --- a/coq/ethereum/istanbul/state.v +++ b/coq/ethereum/istanbul/state.v @@ -1,3 +1,4 @@ +(* Generated *) (* State ^^^^^ @@ -22,10 +23,10 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require istanbul.fork_types. -Require istanbul.trie. +Require ethereum.istanbul.fork_types. +Require ethereum.istanbul.trie. -Definition close_state : M unit := +Definition close_state (state : State) : M unit := (* Free resources held by the state. Used by optimized implementations to release file descriptors. @@ -34,9 +35,9 @@ Definition close_state : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition begin_transaction : M unit := +Definition begin_transaction (state : State) : M unit := (* Start a state transaction. @@ -48,12 +49,12 @@ Definition begin_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition commit_transaction : M unit := +Definition commit_transaction (state : State) : M unit := (* Commit a state transaction. @@ -62,13 +63,13 @@ Definition commit_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["pop"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition rollback_transaction : M unit := +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. @@ -80,9 +81,9 @@ Definition rollback_transaction : M unit := *) (* TODO assignment *) (* TODO statement *) + M.pure tt. - -Definition get_account : M unit := +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. @@ -102,14 +103,16 @@ Definition get_account : M unit := account : `Account` Account at address. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition get_account_optional : M unit := +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. @@ -126,14 +129,16 @@ Definition get_account_optional : M unit := account : `Account` Account at address. *) - let* account := trie.trie_get (| - state.["_main_trie"], - address - |) in + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition set_account : M unit := +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()`). @@ -147,14 +152,14 @@ Definition set_account : M unit := account : `Account` Account to set at address. *) - do* trie.trie_set (| - state.["_main_trie"], + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), address, account - |) in + |) ]] in + M.pure tt. - -Definition destroy_account : M unit := +Definition destroy_account (state : State) (address : Address) : M unit := (* Completely remove the account at `address` and all of its storage. @@ -169,18 +174,18 @@ Definition destroy_account : M unit := address : `Address` Address of account to destroy. *) - do* destroy_storage (| + do* [[ M.get_local ~(| "destroy_storage" |) ~(| state, address - |) in - do* set_account (| + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - (* TODO expression *) - |) in + tt + |) ]] in + M.pure tt. - -Definition destroy_storage : M unit := +Definition destroy_storage (state : State) (address : Address) : M unit := (* Completely remove the storage at `address`. @@ -192,9 +197,9 @@ Definition destroy_storage : M unit := Address of account whose storage is to be deleted. *) (* TODO statement *) + M.pure tt. - -Definition mark_account_created : M unit := +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 @@ -211,12 +216,12 @@ Definition mark_account_created : M unit := address : `Address` Address of the account that has been created. *) - do* state.["created_accounts"].["add"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| address - |) in - + |) ]] in + M.pure tt. -Definition get_storage : M unit := +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. @@ -235,19 +240,23 @@ Definition get_storage : M unit := value : `U256` Value at the key. *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition set_storage : M unit := +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. @@ -264,19 +273,21 @@ Definition set_storage : M unit := Value to set at the key. *) (* TODO statement *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - do* trie.trie_set (| - trie, + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), key, value - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition storage_root : M unit := +Definition storage_root (state : State) (address : Address) : M Root := (* Calculate the storage root of an account. @@ -294,9 +305,9 @@ Definition storage_root : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition state_root : M unit := +Definition state_root (state : State) : M Root := (* Calculate the state root. @@ -313,9 +324,9 @@ Definition state_root : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition account_exists : M unit := +Definition account_exists (state : State) (address : Address) : M bool := (* Checks if an account exists in the state trie @@ -332,9 +343,9 @@ Definition account_exists : M unit := True if account exists in the state trie, False otherwise *) (* TODO statement *) + M.pure tt. - -Definition account_has_code_or_nonce : M unit := +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := (* Checks if an account has non zero nonce or non empty code @@ -351,14 +362,16 @@ Definition account_has_code_or_nonce : M unit := True if if an account has non zero nonce or non empty code, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_empty : M unit := +Definition is_account_empty (state : State) (address : Address) : M bool := (* Checks if an account has zero nonce, empty code and zero balance. @@ -375,14 +388,16 @@ Definition is_account_empty : M unit := True if if an account has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition account_exists_and_is_empty : M unit := +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. @@ -400,14 +415,16 @@ Definition account_exists_and_is_empty : M unit := True if an account exists and has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_alive : M unit := +Definition is_account_alive (state : State) (address : Address) : M bool := (* Check whether is an account is both in the state and non empty. @@ -423,49 +440,51 @@ Definition is_account_alive : M unit := is_alive : `bool` True if the account is alive. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition modify_state : M unit := +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := (* Modify an `Account` in the `State`. *) - do* set_account (| + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - ethereum_types.frozen.modify (| - get_account (| + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| state, address |), f |) - |) in - + |) ]] in + M.pure tt. -Definition move_ether : M unit := +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := (* Move funds between accounts. *) (* TODO statement *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, sender_address, - reduce_sender_balance - |) in - do* modify_state (| + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| state, recipient_address, - increase_recipient_balance - |) in - + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. -Definition set_account_balance : M unit := +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := (* Sets the balance of an account. @@ -481,14 +500,14 @@ Definition set_account_balance : M unit := The amount that needs to set in balance. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - set_balance - |) in + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. - -Definition touch_account : M unit := +Definition touch_account (state : State) (address : Address) : M unit := (* Initializes an account to state. @@ -501,9 +520,9 @@ Definition touch_account : M unit := The address of the account that need to initialised. *) (* TODO statement *) + M.pure tt. - -Definition increment_nonce : M unit := +Definition increment_nonce (state : State) (address : Address) : M unit := (* Increments the nonce of an account. @@ -516,14 +535,14 @@ Definition increment_nonce : M unit := Address of the account whose nonce needs to be incremented. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_nonce - |) in + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. - -Definition set_code : M unit := +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := (* Sets Account code. @@ -539,14 +558,14 @@ Definition set_code : M unit := The bytecode that needs to be set. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - write_code - |) in - + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. -Definition create_ether : M unit := +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := (* Add newly created ether to an account. @@ -560,14 +579,14 @@ Definition create_ether : M unit := The amount of ether to be added to the account of interest. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_balance - |) in - + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. -Definition get_storage_original : M unit := +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 @@ -584,10 +603,12 @@ Definition get_storage_original : M unit := *) (* TODO statement *) (* TODO assignment *) - let* original_account_trie := original_trie.["get"] (| - address - |) in + 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.v b/coq/ethereum/istanbul/transactions.v index 85bf639bfb..dccbd94f85 100644 --- a/coq/ethereum/istanbul/transactions.v +++ b/coq/ethereum/istanbul/transactions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, @@ -9,4 +10,4 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require istanbul.fork_types. +Require ethereum.istanbul.fork_types. diff --git a/coq/ethereum/istanbul/trie.v b/coq/ethereum/istanbul/trie.v index 548de91e1c..6b8953f256 100644 --- a/coq/ethereum/istanbul/trie.v +++ b/coq/ethereum/istanbul/trie.v @@ -1,3 +1,4 @@ +(* Generated *) (* State Trie ^^^^^^^^^^ @@ -14,7 +15,7 @@ The state trie is the structure responsible for storing *) -Definition encode_internal_node : M unit := +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 @@ -35,22 +36,24 @@ Definition encode_internal_node : M unit := *) (* TODO statement *) (* TODO statement *) - let* encoded := rlp.["encode"] (| - unencoded - |) in + 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 : M unit := +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 : M unit := +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. @@ -66,9 +69,9 @@ Definition copy_trie : M unit := A copy of the trie. *) (* TODO statement *) + M.pure tt. - -Definition trie_set : M unit := +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := (* Stores an item in a Merkle Trie. @@ -85,9 +88,9 @@ Definition trie_set : M unit := Node to insert at `key`. *) (* TODO statement *) + M.pure tt. - -Definition trie_get : M unit := +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := (* Gets an item from the Merkle Trie. @@ -106,17 +109,17 @@ Definition trie_get : M unit := Node at `key` in the trie. *) (* TODO statement *) + M.pure tt. - -Definition common_prefix_length : M unit := +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 : M unit := +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := (* Compresses nibble-list into a standard byte array with a flag. @@ -150,14 +153,16 @@ Definition nibble_list_to_compact : M unit := compressed : `bytearray` Compact byte array. *) - let* compact := bytearray (| + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition bytes_to_nibble_list : M unit := +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := (* Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). @@ -171,14 +176,16 @@ Definition bytes_to_nibble_list : M unit := nibble_list : `Bytes` The `Bytes` in nibble-list format. *) - let* nibble_list := bytearray (| - (* TODO expression *) - |) in + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _prepare_trie : M unit := +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. @@ -199,9 +206,9 @@ Definition _prepare_trie : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition root : M unit := +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := (* Computes the root of a modified merkle patricia trie (MPT). @@ -219,22 +226,26 @@ Definition root : M unit := root : `.fork_types.Root` MPT root of the underlying key-value pairs. *) - let* obj := _prepare_trie (| - trie, - get_storage_root - |) in - let* root_node := encode_internal_node (| - patricialize (| - obj, - Uint (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) + M.pure tt. - -Definition patricialize : M unit := +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := (* Structural composition function. @@ -254,21 +265,29 @@ Definition patricialize : M unit := Root node of `obj`. *) (* TODO statement *) - let* arbitrary_key := next (| - iter (| - obj - |) - |) in + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in (* TODO statement *) - let* substring := (* TODO expression *) in - let* prefix_length := len (| - substring - |) in + 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 *) - let* value := (* TODO expression *) in + do* M.assign "value" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/istanbul/utils/__init__.v b/coq/ethereum/istanbul/utils/__init__.v index beff4482b1..7f30fe939b 100644 --- a/coq/ethereum/istanbul/utils/__init__.v +++ b/coq/ethereum/istanbul/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions unique to this particular fork. *) diff --git a/coq/ethereum/istanbul/utils/address.v b/coq/ethereum/istanbul/utils/address.v index 4a42f362de..218a3bbba0 100644 --- a/coq/ethereum/istanbul/utils/address.v +++ b/coq/ethereum/istanbul/utils/address.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,9 +19,10 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require istanbul.fork_types. +Require ethereum.__init__. +Require ethereum.istanbul.fork_types. -Definition to_address : M unit := +Definition to_address (data : (* TODO type *)) : M Address := (* Convert a Uint or U256 value to a valid address (20 bytes). @@ -35,9 +37,9 @@ Definition to_address : M unit := The obtained address. *) (* TODO statement *) + M.pure tt. - -Definition compute_contract_address : M unit := +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := (* Computes address of the new account that needs to be created. @@ -54,20 +56,26 @@ Definition compute_contract_address : M unit := address: `Address` The computed address of the new account. *) - let* computed_address := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *) - |) - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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 : M unit := +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. @@ -86,14 +94,22 @@ Definition compute_create2_contract_address : M unit := address: `ethereum.istanbul.fork_types.Address` The computed address of the new account. *) - let* preimage := (* TODO expression *) in - let* computed_address := ethereum.crypto.hash.keccak256 (| - preimage - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/istanbul/utils/hexadecimal.v index c4628f2d15..7cc192c3ba 100644 --- a/coq/ethereum/istanbul/utils/hexadecimal.v +++ b/coq/ethereum/istanbul/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Istanbul types. *) Require ethereum.utils.hexadecimal. -Require istanbul.fork_types. +Require ethereum.istanbul.fork_types. -Definition hex_to_root : M unit := +Definition hex_to_root (hex_string : str) : M Root := (* Convert hex string to trie root. @@ -31,9 +32,9 @@ Definition hex_to_root : M unit := Trie root obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bloom : M unit := +Definition hex_to_bloom (hex_string : str) : M Bloom := (* Convert hex string to bloom. @@ -48,9 +49,9 @@ Definition hex_to_bloom : M unit := Bloom obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_address : M unit := +Definition hex_to_address (hex_string : str) : M Address := (* Convert hex string to Address (20 bytes). @@ -65,4 +66,4 @@ Definition hex_to_address : M unit := The address obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/istanbul/utils/message.v b/coq/ethereum/istanbul/utils/message.v index a57a990418..58d70c6adc 100644 --- a/coq/ethereum/istanbul/utils/message.v +++ b/coq/ethereum/istanbul/utils/message.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For The Message Data-structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,12 +17,12 @@ specification. Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require istanbul.fork_types. -Require istanbul.state. -Require istanbul.vm. -Require istanbul.utils.address. +Require ethereum.istanbul.fork_types. +Require ethereum.istanbul.state. +Require ethereum.istanbul.vm. +Require ethereum.istanbul.utils.address. -Definition prepare_message : M unit := +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. @@ -56,4 +57,4 @@ Definition prepare_message : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/__init__.v b/coq/ethereum/istanbul/vm/__init__.v index 51466b0c1e..ee3f398c83 100644 --- a/coq/ethereum/istanbul/vm/__init__.v +++ b/coq/ethereum/istanbul/vm/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,12 +19,12 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require istanbul.blocks. -Require istanbul.fork_types. -Require istanbul.state. -Require istanbul.vm.precompiled_contracts. +Require ethereum.istanbul.blocks. +Require ethereum.istanbul.fork_types. +Require ethereum.istanbul.state. +Require ethereum.istanbul.vm.precompiled_contracts. -Definition incorporate_child_on_success : M unit := +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of a successful `child_evm` into the parent `evm`. @@ -34,19 +35,25 @@ Definition incorporate_child_on_success : M unit := 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 *) - (* TODO statement *) - (* TODO statement *) - do* evm.["accounts_to_delete"].["update"] (| - child_evm.["accounts_to_delete"] - |) in - do* evm.["touched_accounts"].["update"] (| - child_evm.["touched_accounts"] - |) in - (* TODO statement *) + M.pure tt. - -Definition incorporate_child_on_error : M unit := +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. @@ -59,5 +66,7 @@ Definition incorporate_child_on_error : M unit := *) (* TODO statement *) (* 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.v b/coq/ethereum/istanbul/vm/exceptions.v index 1784494410..47e26555d5 100644 --- a/coq/ethereum/istanbul/vm/exceptions.v +++ b/coq/ethereum/istanbul/vm/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Exceptions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/istanbul/vm/gas.v b/coq/ethereum/istanbul/vm/gas.v index fc4bea6483..c7bbce3e4a 100644 --- a/coq/ethereum/istanbul/vm/gas.v +++ b/coq/ethereum/istanbul/vm/gas.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Gas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,9 +18,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.trace. Require ethereum.utils.numeric. -Require istanbul.vm.exceptions. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.exceptions. -Definition charge_gas : M unit := +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := (* Subtracts `amount` from `evm.gas_left`. @@ -31,18 +33,18 @@ Definition charge_gas : M unit := The amount of gas the current operation requires. *) - do* ethereum.trace.evm_trace (| + do* [[ ethereum.trace.evm_trace ~(| evm, - ethereum.trace.GasAndRefund (| - int (| + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| amount |) |) - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_memory_gas_cost : M unit := +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, @@ -58,14 +60,22 @@ Definition calculate_memory_gas_cost : M unit := total_gas_cost : `ethereum.base_types.Uint` The gas cost for storing data in memory. *) - let* size_in_words := (* TODO expression *) in - let* linear_cost := (* TODO expression *) in - let* quadratic_cost := (* TODO expression *) in - let* total_gas_cost := (* TODO expression *) in + 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 : M unit := +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := (* Calculates the gas amount to extend memory @@ -81,22 +91,28 @@ Definition calculate_gas_extend_memory : M unit := ------- extend_memory: `ExtendMemory` *) - let* size_to_extend := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* to_be_paid := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* current_size := ethereum_types.numeric.Uint (| - len (| - memory - |) - |) in + 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 : M unit := +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. @@ -122,18 +138,22 @@ Definition calculate_message_call_gas : M unit := ------- message_call_gas: `MessageCallGas` *) - let* call_stipend := (* TODO expression *) in + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* gas := min (| - gas, - max_message_call_gas (| - (* TODO expression *) - |) - |) in + 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 : M unit := +Definition max_message_call_gas (gas : Uint) : M Uint := (* Calculates the maximum gas that is allowed for making a message call @@ -148,4 +168,4 @@ Definition max_message_call_gas : M unit := The maximum gas allowed for making the message-call. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/instructions/__init__.v b/coq/ethereum/istanbul/vm/instructions/__init__.v index b36b1ebfef..cbd7e7e63a 100644 --- a/coq/ethereum/istanbul/vm/instructions/__init__.v +++ b/coq/ethereum/istanbul/vm/instructions/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* EVM Instruction Encoding (Opcodes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/istanbul/vm/instructions/arithmetic.v b/coq/ethereum/istanbul/vm/instructions/arithmetic.v index 0de6949ccd..b887ac7471 100644 --- a/coq/ethereum/istanbul/vm/instructions/arithmetic.v +++ b/coq/ethereum/istanbul/vm/instructions/arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,11 @@ Implementations of the EVM Arithmetic instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require istanbul.vm.gas. -Require istanbul.vm.stack. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.stack. -Definition add : M unit := +Definition add (evm : Evm) : M unit := (* Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -28,27 +30,37 @@ Definition add : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_add"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sub (evm : Evm) : M unit := (* Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -59,27 +71,37 @@ Definition sub : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_sub"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mul (evm : Evm) : M unit := (* Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -90,27 +112,37 @@ Definition mul : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_mul"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition div (evm : Evm) : M unit := (* Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -121,25 +153,33 @@ Definition div : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |) in - let* divisor := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - quotient - |) 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 : M unit := +Definition sdiv (evm : Evm) : M unit := (* Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -150,31 +190,39 @@ Definition sdiv : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* divisor := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - quotient + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mod : M unit := +Definition mod (evm : Evm) : M unit := (* Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -185,25 +233,33 @@ Definition mod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - remainder - |) in + |) ]] 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 : M unit := +Definition smod (evm : Evm) : M unit := (* Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -214,31 +270,39 @@ Definition smod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* y := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - remainder + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition addmod : M unit := +Definition addmod (evm : Evm) : M unit := (* Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -249,34 +313,44 @@ Definition addmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +Definition mulmod (evm : Evm) : M unit := (* Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -287,34 +361,44 @@ Definition mulmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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 : M unit := +Definition exp (evm : Evm) : M unit := (* Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -325,39 +409,53 @@ Definition exp : M unit := The current EVM frame. *) - let* base := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent_bits := exponent.["bit_length"] (| - - |) in - let* exponent_bytes := (* TODO expression *) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - pow (| - base, - exponent, - (* 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 - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition signextend : M unit := +Definition signextend (evm : Evm) : M unit := (* Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -368,20 +466,28 @@ Definition signextend : M unit := The current EVM frame. *) - let* byte_num := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/istanbul/vm/instructions/bitwise.v index c62b7f7510..579f9bffee 100644 --- a/coq/ethereum/istanbul/vm/instructions/bitwise.v +++ b/coq/ethereum/istanbul/vm/instructions/bitwise.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Bitwise Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM bitwise instructions. *) Require ethereum_types.numeric. -Require istanbul.vm.gas. -Require istanbul.vm.stack. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.stack. -Definition bitwise_and : M unit := +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. @@ -27,24 +29,32 @@ Definition bitwise_and : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_or : M unit := +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. @@ -55,24 +65,32 @@ Definition bitwise_or : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_xor : M unit := +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. @@ -83,24 +101,32 @@ Definition bitwise_xor : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_not : M unit := +Definition bitwise_not (evm : Evm) : M unit := (* Bitwise NOT operation of the top element of the stack. Pushes the result back on the stack. @@ -111,21 +137,27 @@ Definition bitwise_not : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition get_byte : M unit := +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 @@ -137,25 +169,33 @@ Definition get_byte : M unit := The current EVM frame. *) - let* byte_index := stack.pop (| - evm.["stack"] - |) in - let* word := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -164,29 +204,37 @@ Definition bitwise_shl : M unit := evm : The current EVM frame. *) - let* shift := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -195,25 +243,33 @@ Definition bitwise_shr : M unit := evm : The current EVM frame. *) - let* shift := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -222,24 +278,32 @@ Definition bitwise_sar : M unit := evm : The current EVM frame. *) - let* shift := int (| - stack.pop (| - evm.["stack"] - |) - |) in - let* signed_value := stack.pop (| - evm.["stack"] - |).["to_signed"] (| + 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 - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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.v b/coq/ethereum/istanbul/vm/instructions/block.v index cefae915dd..6d34d6ab14 100644 --- a/coq/ethereum/istanbul/vm/instructions/block.v +++ b/coq/ethereum/istanbul/vm/instructions/block.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Block Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM block instructions. *) Require ethereum_types.numeric. -Require istanbul.vm.gas. -Require istanbul.vm.stack. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.stack. -Definition block_hash : M unit := +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. @@ -27,27 +29,35 @@ Definition block_hash : M unit := The current EVM frame. *) - let* block_number := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* max_block_number := (* TODO expression *) in + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition coinbase : M unit := +Definition coinbase (evm : Evm) : M unit := (* Push the current block's beneficiary address (address of the block miner) onto the stack. @@ -62,20 +72,24 @@ Definition coinbase : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["coinbase"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition timestamp : M unit := +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. @@ -90,18 +104,22 @@ Definition timestamp : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["env"].["time"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition number (evm : Evm) : M unit := (* Push the current block's number onto the stack. @@ -115,20 +133,24 @@ Definition number : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["number"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition difficulty : M unit := +Definition difficulty (evm : Evm) : M unit := (* Push the current block's difficulty onto the stack. @@ -142,20 +164,24 @@ Definition difficulty : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["difficulty"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_limit : M unit := +Definition gas_limit (evm : Evm) : M unit := (* Push the current block's gas limit onto the stack. @@ -169,20 +195,24 @@ Definition gas_limit : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_limit"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition chain_id : M unit := +Definition chain_id (evm : Evm) : M unit := (* Push the chain id onto the stack. @@ -193,15 +223,19 @@ Definition chain_id : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["chain_id"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/istanbul/vm/instructions/comparison.v index 965821babf..ce8667aab5 100644 --- a/coq/ethereum/istanbul/vm/instructions/comparison.v +++ b/coq/ethereum/istanbul/vm/instructions/comparison.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Comparison Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM Comparison instructions. *) Require ethereum_types.numeric. -Require istanbul.vm.gas. -Require istanbul.vm.stack. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.stack. -Definition less_than : M unit := +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. @@ -27,27 +29,37 @@ Definition less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_less_than : M unit := + |) ]] 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. @@ -57,31 +69,41 @@ Definition signed_less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition greater_than : M unit := + |) ]] 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. @@ -92,27 +114,37 @@ Definition greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_greater_than : M unit := + |) ]] 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. @@ -122,31 +154,41 @@ Definition signed_greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition equal : M unit := + |) ]] 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. @@ -157,27 +199,37 @@ Definition equal : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition is_zero : M unit := + |) ]] 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. @@ -188,19 +240,27 @@ Definition is_zero : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/istanbul/vm/instructions/control_flow.v index 109de0bba2..4c5791a1ee 100644 --- a/coq/ethereum/istanbul/vm/instructions/control_flow.v +++ b/coq/ethereum/istanbul/vm/instructions/control_flow.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Control Flow Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM control flow instructions. *) Require ethereum_types.numeric. -Require istanbul.vm.gas. -Require istanbul.vm.exceptions. -Require istanbul.vm.stack. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.exceptions. +Require ethereum.istanbul.vm.stack. -Definition stop : M unit := +Definition stop (evm : Evm) : M unit := (* Stop further execution of EVM code. @@ -29,10 +31,14 @@ Definition stop : M unit := (* TODO statement *) (* TODO statement *) (* TODO assignment *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jump : M unit := +Definition jump (evm : Evm) : M unit := (* Alter the program counter to the location specified by the top of the stack. @@ -43,20 +49,22 @@ Definition jump : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition jumpi : M unit := +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 @@ -68,23 +76,27 @@ Definition jumpi : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* conditional_value := stack.pop (| - evm.["stack"] - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition pc : M unit := +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. @@ -96,20 +108,24 @@ Definition pc : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["pc"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_left : M unit := +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. @@ -121,20 +137,24 @@ Definition gas_left : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["gas_left"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jumpdest : M unit := +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 @@ -147,10 +167,14 @@ Definition jumpdest : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_JUMPDEST - |) in - (* TODO statement *) + |) ]] 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.v b/coq/ethereum/istanbul/vm/instructions/environment.v index aa19a01e41..a051868a52 100644 --- a/coq/ethereum/istanbul/vm/instructions/environment.v +++ b/coq/ethereum/istanbul/vm/instructions/environment.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,15 +16,16 @@ Implementations of the EVM environment related instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require istanbul.fork_types. -Require istanbul.state. -Require istanbul.utils.address. -Require istanbul.vm.memory. -Require istanbul.vm.exceptions. -Require istanbul.vm.gas. -Require istanbul.vm.stack. - -Definition address : M unit := +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. @@ -34,20 +36,24 @@ Definition address : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["current_target"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition balance : M unit := +Definition balance (evm : Evm) : M unit := (* Pushes the balance of the given account onto the stack. @@ -57,27 +63,35 @@ Definition balance : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* balance := state.get_account (| - evm.["env"].["state"], - address - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +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. @@ -89,20 +103,24 @@ Definition origin : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["origin"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition caller : M unit := +Definition caller (evm : Evm) : M unit := (* Pushes the address of the caller onto the stack. @@ -113,20 +131,24 @@ Definition caller : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["caller"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition callvalue : M unit := +Definition callvalue (evm : Evm) : M unit := (* Push the value (in wei) sent with the call onto the stack. @@ -137,18 +159,22 @@ Definition callvalue : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["message"].["value"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition calldataload (evm : Evm) : M unit := (* Push a word (32 bytes) of the input data belonging to the current environment onto the stack. @@ -159,30 +185,38 @@ Definition calldataload : M unit := The current EVM frame. *) - let* start_index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - start_index, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] 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* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - value + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 |) - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition calldatasize : M unit := +Definition calldatasize (evm : Evm) : M unit := (* Push the size of input data in current environment onto the stack. @@ -193,22 +227,26 @@ Definition calldatasize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["message"].["data"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition calldatacopy : M unit := +Definition calldatacopy (evm : Evm) : M unit := (* Copy a portion of the input data in current environment to memory. @@ -221,40 +259,60 @@ Definition calldatacopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* data_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - data_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition codesize (evm : Evm) : M unit := (* Push the size of code running in current environment onto the stack. @@ -265,22 +323,26 @@ Definition codesize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["code"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition codecopy : M unit := +Definition codecopy (evm : Evm) : M unit := (* Copy a portion of the code in current environment to memory. @@ -293,40 +355,60 @@ Definition codecopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["code"], - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition gasprice (evm : Evm) : M unit := (* Push the gas price used in current environment onto the stack. @@ -337,20 +419,24 @@ Definition gasprice : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_price"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition extcodesize : M unit := +Definition extcodesize (evm : Evm) : M unit := (* Push the code size of a given account onto the stack. @@ -360,31 +446,39 @@ Definition extcodesize : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* codesize := ethereum_types.numeric.U256 (| - len (| - state.get_account (| - evm.["env"].["state"], - address - |).["code"] + |) ]] 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 - do* stack.push (| - evm.["stack"], - codesize - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition extcodecopy : M unit := +Definition extcodecopy (evm : Evm) : M unit := (* Copy a portion of an account's code to memory. @@ -394,49 +488,73 @@ Definition extcodecopy : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* code := state.get_account (| - evm.["env"].["state"], - address - |).["code"] in - let* value := vm.memory.buffer_read (| - code, - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition returndatasize (evm : Evm) : M unit := (* Pushes the size of the return data buffer onto the stack. @@ -446,22 +564,26 @@ Definition returndatasize : M unit := The current EVM frame. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["return_data"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition returndatacopy : M unit := +Definition returndatacopy (evm : Evm) : M unit := (* Copies data from the return data buffer code to memory @@ -470,37 +592,57 @@ Definition returndatacopy : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* return_data_start_position := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - (* TODO statement *) - let* value := (* TODO expression *) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) 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 : M unit := +Definition extcodehash (evm : Evm) : M unit := (* Returns the keccak256 hash of a contract’s bytecode Parameters @@ -508,28 +650,36 @@ Definition extcodehash : M unit := evm : The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* account := state.get_account (| - evm.["env"].["state"], - address - |) in - (* TODO statement *) - do* stack.push (| - evm.["stack"], - codehash - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition self_balance (evm : Evm) : M unit := (* Pushes the balance of the current address to the stack. @@ -540,17 +690,23 @@ Definition self_balance : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_FAST_STEP - |) in - let* balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/istanbul/vm/instructions/keccak.v index 663bb54e6c..49f1dcc927 100644 --- a/coq/ethereum/istanbul/vm/instructions/keccak.v +++ b/coq/ethereum/istanbul/vm/instructions/keccak.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Keccak Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM keccak instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require istanbul.vm.gas. -Require istanbul.vm.memory. -Require istanbul.vm.stack. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.memory. +Require ethereum.istanbul.vm.stack. -Definition keccak : M unit := +Definition keccak (evm : Evm) : M unit := (* Pushes to the stack the Keccak-256 hash of a region of memory. @@ -32,36 +34,56 @@ Definition keccak : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* word_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in - let* hash := ethereum.crypto.hash.keccak256 (| - data - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/istanbul/vm/instructions/log.v index 6c9c08c1a5..f57792524a 100644 --- a/coq/ethereum/istanbul/vm/instructions/log.v +++ b/coq/ethereum/istanbul/vm/instructions/log.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Logging Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,13 +15,14 @@ Implementations of the EVM logging instructions. Require functools. Require ethereum_types.numeric. -Require istanbul.blocks. -Require istanbul.vm.exceptions. -Require istanbul.vm.gas. -Require istanbul.vm.memory. -Require istanbul.vm.stack. +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 : M unit := +Definition log_n (evm : Evm) (num_topics : U256) : M unit := (* Appends a log entry, having `num_topics` topics, to the evm logs. @@ -35,27 +37,43 @@ Definition log_n : M unit := The number of topics to be included in the log entry. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* topics := (* TODO expression *) in + 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 *) - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in (* TODO statement *) - let* log_entry := blocks.Log (| + do* M.assign "log_entry" [[ + blocks.Log ~(| - |) in + |) in + ]] in (* TODO assignment *) - (* 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/memory.v b/coq/ethereum/istanbul/vm/instructions/memory.v index 5101da63be..5a8020e554 100644 --- a/coq/ethereum/istanbul/vm/instructions/memory.v +++ b/coq/ethereum/istanbul/vm/instructions/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM Memory instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require istanbul.vm.gas. -Require istanbul.vm.memory. -Require istanbul.vm.stack. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.memory. +Require ethereum.istanbul.vm.stack. -Definition mstore : M unit := +Definition mstore (evm : Evm) : M unit := (* Stores a word to memory. This also expands the memory, if the memory is @@ -30,32 +32,44 @@ Definition mstore : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* memory.memory_write (| - evm.["memory"], - start_position, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mstore8 (evm : Evm) : M unit := (* Stores a byte to memory. This also expands the memory, if the memory is @@ -67,33 +81,47 @@ Definition mstore8 : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ (* TODO expression *) - |) in - do* memory.memory_write (| - evm.["memory"], - start_position, - normalized_bytes_value - |) in - (* TODO statement *) - + ]] 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 : M unit := +Definition mload (evm : Evm) : M unit := (* Load word from memory. @@ -103,35 +131,47 @@ Definition mload : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.memory_read_bytes (| - evm.["memory"], - start_position, - ethereum_types.numeric.U256 (| - (* 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 - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition msize : M unit := +Definition msize (evm : Evm) : M unit := (* Push the size of active memory in bytes onto the stack. @@ -142,17 +182,21 @@ Definition msize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["memory"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/istanbul/vm/instructions/stack.v index 02257068ac..656d6fb2e3 100644 --- a/coq/ethereum/istanbul/vm/instructions/stack.v +++ b/coq/ethereum/istanbul/vm/instructions/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM stack related instructions. Require functools. Require ethereum_types.numeric. -Require istanbul.vm.exceptions. -Require istanbul.vm.gas. -Require istanbul.vm.memory. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.exceptions. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.memory. -Definition pop : M unit := +Definition pop (evm : Evm) : M unit := (* Remove item from stack. @@ -28,18 +30,22 @@ Definition pop : M unit := The current EVM frame. *) - do* stack.["pop"] (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in + |) ]] in (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition push_n : M unit := +Definition push_n (evm : Evm) (num_bytes : int) : M unit := (* Pushes a N-byte immediate onto the stack. @@ -54,29 +60,33 @@ Definition push_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - evm.["code"], - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - num_bytes + |) ]] 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 - do* stack.["push"] (| - evm.["stack"], - data_to_push - |) in - (* TODO statement *) - - -Definition dup_n : M unit := + |) 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. @@ -91,20 +101,26 @@ Definition dup_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - let* data_to_duplicate := (* TODO expression *) in - do* stack.["push"] (| - evm.["stack"], - data_to_duplicate - |) 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 : M unit := +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. @@ -123,11 +139,15 @@ Definition swap_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - (* 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/storage.v b/coq/ethereum/istanbul/vm/instructions/storage.v index 5d029d4e48..5776260122 100644 --- a/coq/ethereum/istanbul/vm/instructions/storage.v +++ b/coq/ethereum/istanbul/vm/instructions/storage.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Storage Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,12 +14,13 @@ Implementations of the EVM storage related instructions. *) Require ethereum_types.numeric. -Require istanbul.state. -Require istanbul.vm.exceptions. -Require istanbul.vm.gas. -Require istanbul.vm.stack. +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 : M unit := +Definition sload (evm : Evm) : M unit := (* Loads to the stack, the value corresponding to a certain key from the storage of the current account. @@ -29,28 +31,36 @@ Definition sload : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_SLOAD - |) in - let* value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sstore (evm : Evm) : M unit := (* Stores a value at a certain key in the current context's storage. @@ -60,37 +70,49 @@ Definition sstore : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in (* TODO statement *) - let* original_value := state.get_storage_original (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - let* current_value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in + M.get_local ~(| "gas_cost" |) + |) ]] in (* TODO statement *) - do* state.set_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key, - new_value - |) 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.v b/coq/ethereum/istanbul/vm/instructions/system.v index 797d870b3d..ff5f1bf015 100644 --- a/coq/ethereum/istanbul/vm/instructions/system.v +++ b/coq/ethereum/istanbul/vm/instructions/system.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) System Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,54 +16,69 @@ Implementations of the EVM system related instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require istanbul.fork_types. -Require istanbul.state. -Require istanbul.utils.address. -Require istanbul.vm.exceptions. -Require istanbul.vm.gas. -Require istanbul.vm.memory. -Require istanbul.vm.stack. - -Definition generic_create : M unit := +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 *) - let* create_message_gas := gas.max_message_call_gas (| - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |) - |) in - (* 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 *) - let* sender_address := evm.["message"].["current_target"] in - let* sender := state.get_account (| - evm.["env"].["state"], - sender_address - |) in - (* TODO statement *) - (* TODO statement *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) in - do* state.increment_nonce (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |) in - let* child_message := Message (| - - |) in - let* child_evm := process_create_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - - -Definition create : M unit := + 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. @@ -71,42 +87,58 @@ Definition create : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_contract_address (| - evm.["message"].["current_target"], - state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["nonce"] - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition create2 (evm : Evm) : M unit := (* Creates a new account with associated code. @@ -118,50 +150,70 @@ Definition create2 : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* salt := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* call_data_words := (* TODO expression *) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_create2_contract_address (| - evm.["message"].["current_target"], - salt, - memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size - |) in - (* TODO statement *) - + 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_ : M unit := +Definition return_ (evm : Evm) : M unit := (* Halts execution returning output data. @@ -170,66 +222,84 @@ Definition return_ : M unit := evm : The current EVM frame. *) - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) + |) ]] 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 : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_input_start_position, - memory_input_size - |) in - let* code := state.get_account (| - evm.["env"].["state"], - code_address - |).["code"] in - let* child_message := Message (| - - |) in - let* child_evm := process_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - let* actual_output_size := min (| - memory_output_size, - ethereum_types.numeric.U256 (| - len (| - child_evm.["output"] + 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 - do* memory.memory_write (| - evm.["memory"], + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), memory_output_start_position, (* TODO expression *) - |) in + |) ]] in + M.pure tt. - -Definition call : M unit := +Definition call (evm : Evm) : M unit := (* Message-call into an account. @@ -238,61 +308,91 @@ Definition call : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* create_gas_cost := (* TODO expression *) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) - (* 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 : M unit := +Definition callcode (evm : Evm) : M unit := (* Message-call into this account with alternative account’s code. @@ -301,60 +401,90 @@ Definition callcode : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* to := evm.["message"].["current_target"] in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) - (* TODO statement *) - + |) ]] 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 : M unit := +Definition selfdestruct (evm : Evm) : M unit := (* Halt execution and register account for later deletion. @@ -363,52 +493,66 @@ Definition selfdestruct : M unit := evm : The current EVM frame. *) - let* beneficiary := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* gas_cost := gas.GAS_SELF_DESTRUCT in - (* TODO statement *) - let* originator := evm.["message"].["current_target"] in - let* refunded_accounts := evm.["accounts_to_delete"] in - let* parent_evm := evm.["message"].["parent_evm"] in - (* TODO statement *) - (* TODO statement *) - do* gas.charge_gas (| + 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, - gas_cost - |) in - (* TODO statement *) - let* beneficiary_balance := state.get_account (| - evm.["env"].["state"], - beneficiary - |).["balance"] in - let* originator_balance := state.get_account (| - evm.["env"].["state"], - originator - |).["balance"] in - do* state.set_account_balance (| - evm.["env"].["state"], - beneficiary, + 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 (| - evm.["env"].["state"], - originator, - ethereum_types.numeric.U256 (| - (* 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* evm.["accounts_to_delete"].["add"] (| - originator - |) in + |) ]] 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 : M unit := +Definition delegatecall (evm : Evm) : M unit := (* Message-call into an account. @@ -417,66 +561,88 @@ Definition delegatecall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - gas.GAS_CALL - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - evm.["message"].["value"], - evm.["message"].["caller"], - evm.["message"].["current_target"], - code_address, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition staticcall (evm : Evm) : M unit := (* Message-call into an account. @@ -485,68 +651,90 @@ Definition staticcall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - gas.GAS_CALL - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - ethereum_types.numeric.U256 (| - (* TODO expression *) + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 |), - evm.["message"].["current_target"], - to, - to, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +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 @@ -555,27 +743,37 @@ Definition revert : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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, - extend_memory.["cost"] - |) in - (* TODO statement *) - let* output := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in + 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.v b/coq/ethereum/istanbul/vm/interpreter.v index 8c6b78f1fe..00b0112fcb 100644 --- a/coq/ethereum/istanbul/vm/interpreter.v +++ b/coq/ethereum/istanbul/vm/interpreter.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Interpreter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +18,18 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.trace. -Require istanbul.blocks. -Require istanbul.fork_types. -Require istanbul.state. -Require istanbul.vm. -Require istanbul.vm.gas. -Require istanbul.vm.precompiled_contracts.mapping. -Require istanbul.vm.exceptions. -Require istanbul.vm.instructions. -Require istanbul.vm.runtime. - -Definition process_message_call : M unit := +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`. @@ -47,19 +49,21 @@ Definition process_message_call : M unit := *) (* TODO statement *) (* TODO statement *) - let* tx_end := ethereum.trace.TransactionEnd (| - (* TODO expression *), - evm.["output"], - evm.["error"] - |) in - do* ethereum.trace.evm_trace (| - evm, - tx_end - |) in + 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 : M unit := +Definition process_create_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -75,30 +79,32 @@ Definition process_create_message : M unit := evm: :py:class:`~ethereum.istanbul.vm.Evm` Items containing execution specific objects. *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.destroy_storage (| - env.["state"], - message.["current_target"] - |) in - do* state.mark_account_created (| - env.["state"], - message.["current_target"] - |) in - do* state.increment_nonce (| - env.["state"], - message.["current_target"] - |) in - let* evm := process_message (| - message, - env - |) in + 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 : M unit := +Definition process_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -115,23 +121,25 @@ Definition process_message : M unit := Items containing execution specific objects *) (* TODO statement *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.touch_account (| - env.["state"], - message.["current_target"] - |) in + 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 *) - let* evm := execute_code (| - message, - env - |) in + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition execute_code : M unit := +Definition execute_code (message : Message) (env : Environment) : M Evm := (* Executes bytecode present in the `message`. @@ -147,13 +155,19 @@ Definition execute_code : M unit := evm: `ethereum.vm.EVM` Items containing execution specific objects *) - let* code := message.["code"] in - let* valid_jump_destinations := runtime.get_valid_jump_destinations (| - code - |) in - let* evm := Evm (| - - |) in + 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.v b/coq/ethereum/istanbul/vm/memory.v index 94b6a44639..88b516318f 100644 --- a/coq/ethereum/istanbul/vm/memory.v +++ b/coq/ethereum/istanbul/vm/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.byte. -Definition memory_write : M unit := +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := (* Writes to memory. @@ -30,9 +31,9 @@ Definition memory_write : M unit := Data to write to memory. *) (* TODO assignment *) + M.pure tt. - -Definition memory_read_bytes : M unit := +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := (* Read bytes from memory. @@ -51,9 +52,9 @@ Definition memory_read_bytes : M unit := Data read from memory. *) (* TODO statement *) + M.pure tt. - -Definition buffer_read : M unit := +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := (* Read bytes from a buffer. Padding with zeros if necessary. @@ -72,4 +73,4 @@ Definition buffer_read : M unit := Data read from memory. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/__init__.v b/coq/ethereum/istanbul/vm/precompiled_contracts/__init__.v index 675a96d4e0..dabf66a6c6 100644 --- a/coq/ethereum/istanbul/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,4 +14,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require istanbul.utils.hexadecimal. +Require ethereum.istanbul.utils.hexadecimal. diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.v index 3ba57da591..421c8dbcc2 100644 --- a/coq/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.v +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,12 +15,12 @@ Implementation of the ALT_BN128 precompiled contracts. Require ethereum_types.numeric. Require ethereum.crypto.alt_bn128. -Require istanbul.vm. -Require istanbul.vm.gas. -Require istanbul.vm.memory. -Require istanbul.vm.exceptions. +Require ethereum.istanbul.vm. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.memory. +Require ethereum.istanbul.vm.exceptions. -Definition alt_bn128_add : M unit := +Definition alt_bn128_add (evm : Evm) : M unit := (* The ALT_BN128 addition precompiled contract. @@ -28,76 +29,96 @@ Definition alt_bn128_add : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* x1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x1_bytes - |) - |) in - let* y1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y1_bytes - |) - |) in + 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 *) - let* p := (* TODO expression *) in + do* M.assign "p" [[ + (* TODO expression *) in + ]] in (* TODO assignment *) + M.pure tt. - -Definition alt_bn128_mul : M unit := +Definition alt_bn128_mul (evm : Evm) : M unit := (* The ALT_BN128 multiplication precompiled contract. @@ -106,63 +127,77 @@ Definition alt_bn128_mul : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* n := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) (* TODO statement *) - let* p := p0.["mul_by"] (| - n - |) in + 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 : M unit := +Definition alt_bn128_pairing_check (evm : Evm) : M unit := (* The ALT_BN128 pairing check precompiled contract. @@ -171,17 +206,21 @@ Definition alt_bn128_pairing_check : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 (| + ethereum_types.numeric.Uint ~(| (* TODO expression *) |) - |) in + |) ]] in (* TODO statement *) - let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/istanbul/vm/precompiled_contracts/blake2f.v index 93b1faba33..57bdca10e9 100644 --- a/coq/ethereum/istanbul/vm/precompiled_contracts/blake2f.v +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/blake2f.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,11 @@ Implementation of the `Blake2` precompiled contract. *) Require ethereum.crypto.blake2. -Require istanbul.vm. -Require istanbul.vm.gas. -Require istanbul.vm.exceptions. +Require ethereum.istanbul.vm. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.exceptions. -Definition blake2f : M unit := +Definition blake2f (evm : Evm) : M unit := (* Writes the Blake2 hash to output. @@ -26,16 +27,20 @@ Definition blake2f : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in (* TODO statement *) - let* blake2b := ethereum.crypto.blake2.Blake2b (| + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| - |) in + |) in + ]] in (* TODO assignment *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, (* TODO expression *) - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/istanbul/vm/precompiled_contracts/ecrecover.v index f435cce7e6..f0e9bb8dd1 100644 --- a/coq/ethereum/istanbul/vm/precompiled_contracts/ecrecover.v +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/ecrecover.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,11 +17,11 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require istanbul.vm. -Require istanbul.vm.gas. -Require istanbul.vm.memory. +Require ethereum.istanbul.vm. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.memory. -Definition ecrecover : M unit := +Definition ecrecover (evm : Evm) : M unit := (* Decrypts the address using elliptic curve DSA recovery mechanism and writes the address to output. @@ -30,64 +31,80 @@ Definition ecrecover : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* message_hash_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* message_hash := ethereum.crypto.hash.Hash32 (| - message_hash_bytes - |) in - let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + ethereum_types.numeric.U256 ~(| + 32 |) - |) - |) in - let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 + ]] 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 *) - let* address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/istanbul/vm/precompiled_contracts/identity.v index 139cf73308..bf550e5050 100644 --- a/coq/ethereum/istanbul/vm/precompiled_contracts/identity.v +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/identity.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,10 @@ Implementation of the `IDENTITY` precompiled contract. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require istanbul.vm. -Require istanbul.vm.gas. +Require ethereum.istanbul.vm. +Require ethereum.istanbul.vm.gas. -Definition identity : M unit := +Definition identity (evm : Evm) : M unit := (* Writes the message data to output. @@ -26,11 +27,15 @@ Definition identity : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/mapping.v b/coq/ethereum/istanbul/vm/precompiled_contracts/mapping.v index b99612c2e2..6ec0c37466 100644 --- a/coq/ethereum/istanbul/vm/precompiled_contracts/mapping.v +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/mapping.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Mapping of precompiled contracts their implementations. *) Require typing. -Require istanbul.fork_types. -Require istanbul.vm.precompiled_contracts.alt_bn128. -Require istanbul.vm.precompiled_contracts.blake2f. -Require istanbul.vm.precompiled_contracts.ecrecover. -Require istanbul.vm.precompiled_contracts.identity. -Require istanbul.vm.precompiled_contracts.modexp. -Require istanbul.vm.precompiled_contracts.ripemd160. -Require istanbul.vm.precompiled_contracts.sha256. +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.v b/coq/ethereum/istanbul/vm/precompiled_contracts/modexp.v index ca0c8b470c..8fa919e8bb 100644 --- a/coq/ethereum/istanbul/vm/precompiled_contracts/modexp.v +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/modexp.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,100 +15,120 @@ Implementation of the `MODEXP` precompiled contract. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require istanbul.vm. -Require istanbul.vm.gas. -Require istanbul.vm.memory. +Require ethereum.istanbul.vm. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.memory. -Definition modexp : M unit := +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. *) - let* data := evm.["message"].["data"] in - let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) - |) in - let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 - let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* exp_start := (* TODO expression *) in - let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - min (| - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 |), - exp_length + ethereum_types.numeric.U256 ~(| + 32 + |) |) - |) - |) in - do* vm.gas.charge_gas (| + |) 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, - gas_cost (| - base_length, - modulus_length, - exp_length, - exp_head + 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 + |) ]] in (* TODO statement *) - let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - base_length - |) - |) in - let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - exp_length - |) - |) in - let* modulus_start := (* TODO expression *) in - let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - modulus_start, - modulus_length - |) - |) in + 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 : M unit := +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := (* Estimate the complexity of performing a modular exponentiation. @@ -126,18 +147,20 @@ Definition complexity : M unit := complexity : `Uint` Complexity of performing the operation. *) - let* max_length := max (| - ethereum_types.numeric.Uint (| - base_length - |), - ethereum_types.numeric.Uint (| - modulus_length - |) - |) in + 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 : M unit := +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := (* Calculate the number of iterations required to perform a modular exponentiation. @@ -160,9 +183,9 @@ Definition iterations : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition gas_cost : M unit := +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. @@ -188,15 +211,23 @@ Definition gas_cost : M unit := gas_cost : `Uint` Gas required for performing the operation. *) - let* multiplication_complexity := complexity (| - base_length, - modulus_length - |) in - let* iteration_count := iterations (| - exponent_length, - exponent_head - |) in - let* cost := (* TODO expression *) in - (* TODO statement *) + 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.v b/coq/ethereum/istanbul/vm/precompiled_contracts/ripemd160.v index bc5e73dd3c..fe2c66bbe6 100644 --- a/coq/ethereum/istanbul/vm/precompiled_contracts/ripemd160.v +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/ripemd160.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `RIPEMD160` precompiled contract. *) -Definition ripemd160 : M unit := +Definition ripemd160 (evm : Evm) : M unit := (* Writes the ripemd160 hash to output. @@ -22,21 +23,29 @@ Definition ripemd160 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 - let* hash_bytes := hashlib.["new"] (| - (* TODO expression *), - data - |).["digest"] (| - - |) in - let* padded_hash := left_pad_zero_bytes (| - hash_bytes, - (* TODO expression *) - |) in + |) ]] 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.v b/coq/ethereum/istanbul/vm/precompiled_contracts/sha256.v index da6972d411..3ba3ffe7aa 100644 --- a/coq/ethereum/istanbul/vm/precompiled_contracts/sha256.v +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/sha256.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `SHA256` precompiled contract. *) -Definition sha256 : M unit := +Definition sha256 (evm : Evm) : M unit := (* Writes the sha256 hash to output. @@ -22,11 +23,15 @@ Definition sha256 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/runtime.v b/coq/ethereum/istanbul/vm/runtime.v index d13f6e9fbd..caedf31bb2 100644 --- a/coq/ethereum/istanbul/vm/runtime.v +++ b/coq/ethereum/istanbul/vm/runtime.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Runtime Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Runtime related operations used while executing EVM code. Require typing. Require ethereum_types.numeric. -Require istanbul.vm.instructions. +Require ethereum.istanbul.vm.instructions. -Definition get_valid_jump_destinations : M unit := +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := (* Analyze the evm code to obtain the set of valid jump destinations. @@ -38,12 +39,16 @@ Definition get_valid_jump_destinations : M unit := valid_jump_destinations: `Set[Uint]` The set of valid jump destinations in the code. *) - let* valid_jump_destinations := set (| - - |) in - let* pc := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/istanbul/vm/stack.v index b545eac921..513ccc7d9e 100644 --- a/coq/ethereum/istanbul/vm/stack.v +++ b/coq/ethereum/istanbul/vm/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Implementation of the stack operators for the EVM. Require typing. Require ethereum_types.numeric. -Require istanbul.vm.exceptions. +Require ethereum.istanbul.vm.exceptions. -Definition pop : M unit := +Definition pop (stack : (* TODO type *)) : M U256 := (* Pops the top item off of `stack`. @@ -33,9 +34,9 @@ Definition pop : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition push : M unit := +Definition push (stack : (* TODO type *)) (value : U256) : M unit := (* Pushes `value` onto `stack`. @@ -50,4 +51,4 @@ Definition push : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/london/__init__.v b/coq/ethereum/london/__init__.v index d9b3a5d42b..1837593c36 100644 --- a/coq/ethereum/london/__init__.v +++ b/coq/ethereum/london/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* The London fork overhauls the transaction fee market, changes gas refunds, reserves a contract prefix for future use, and delays the difficulty bomb. diff --git a/coq/ethereum/london/blocks.v b/coq/ethereum/london/blocks.v index c3a86f863d..3ff6083ecb 100644 --- a/coq/ethereum/london/blocks.v +++ b/coq/ethereum/london/blocks.v @@ -1,3 +1,4 @@ +(* 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 @@ -14,6 +15,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. -Require london.fork_types. -Require london.transactions. +Require ethereum.crypto.hash. +Require ethereum.london.fork_types. +Require ethereum.london.transactions. diff --git a/coq/ethereum/london/bloom.v b/coq/ethereum/london/bloom.v index 724ded2a41..cac54af7e0 100644 --- a/coq/ethereum/london/bloom.v +++ b/coq/ethereum/london/bloom.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Logs Bloom ^^^^^^^^^^^^^^^^^^^ @@ -19,10 +20,10 @@ eliminating blocks and receipts from their search. Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require london.blocks. -Require london.fork_types. +Require ethereum.london.blocks. +Require ethereum.london.fork_types. -Definition add_to_bloom : M unit := +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := (* Add a bloom entry to the bloom filter (`bloom`). @@ -37,13 +38,15 @@ Definition add_to_bloom : M unit := bloom_entry : An entry which is to be added to bloom filter. *) - let* hash := ethereum.crypto.hash.keccak256 (| - bloom_entry - |) in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition logs_bloom : M unit := +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := (* Obtain the logs bloom from a list of log entries. @@ -63,4 +66,4 @@ Definition logs_bloom : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/london/exceptions.v b/coq/ethereum/london/exceptions.v index 137ea143f6..9a313f6d0e 100644 --- a/coq/ethereum/london/exceptions.v +++ b/coq/ethereum/london/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Exceptions specific to this fork. *) diff --git a/coq/ethereum/london/fork.v b/coq/ethereum/london/fork.v index 27d027a838..342c6f3b10 100644 --- a/coq/ethereum/london/fork.v +++ b/coq/ethereum/london/fork.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^ @@ -20,16 +21,18 @@ Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.ethash. Require ethereum.exceptions. -Require london.blocks. -Require london.bloom. -Require london.fork_types. -Require london.state. -Require london.transactions. -Require london.trie. -Require london.utils.message. -Require london.vm.interpreter. - -Definition apply_fork : M unit := +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. @@ -49,9 +52,9 @@ Definition apply_fork : M unit := Upgraded block chain object for this hard fork. *) (* TODO statement *) + M.pure tt. - -Definition get_last_256_block_hashes : M unit := +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. @@ -71,22 +74,28 @@ Definition get_last_256_block_hashes : M unit := recent_block_hashes : `List[Hash32]` Hashes of the recent 256 blocks in order of increasing block number. *) - let* recent_blocks := (* TODO expression *) in - (* TODO statement *) - let* recent_block_hashes := (* TODO expression *) in - (* TODO statement *) - let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *).["header"] - |) - |) in - do* recent_block_hashes.["append"] (| - most_recent_block_hash - |) in - (* TODO statement *) - - -Definition state_transition : M unit := + 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. @@ -108,43 +117,47 @@ Definition state_transition : M unit := block : Block to apply to `chain`. *) - let* parent_header := (* TODO expression *).["header"] in - do* validate_header (| - block.["header"], - parent_header - |) in - do* validate_ommers (| - block.["ommers"], - block.["header"], + 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 - let* apply_body_output := apply_body (| - chain.["state"], - get_last_256_block_hashes (| - chain - |), - block.["header"].["coinbase"], - block.["header"].["number"], - block.["header"].["base_fee_per_gas"], - block.["header"].["gas_limit"], - block.["header"].["timestamp"], - block.["header"].["difficulty"], - block.["transactions"], - block.["ommers"], - chain.["chain_id"] - |) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - do* chain.["blocks"].["append"] (| + |) ]] 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 + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_base_fee_per_gas : M unit := +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. @@ -164,13 +177,15 @@ Definition calculate_base_fee_per_gas : M unit := base_fee_per_gas : `Uint` Base fee per gas for the block. *) - let* parent_gas_target := (* TODO expression *) in + do* M.assign "parent_gas_target" [[ + (* TODO expression *) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition validate_header : M unit := +Definition validate_header (header : Header) (parent_header : Header) : M unit := (* Verifies a block header. @@ -189,33 +204,41 @@ Definition validate_header : M unit := Parent Header of the header to check for correctness *) (* TODO statement *) - let* expected_base_fee_per_gas := INITIAL_BASE_FEE in + do* M.assign "expected_base_fee_per_gas" [[ + M.get_local ~(| "INITIAL_BASE_FEE" |) in + ]] in (* TODO statement *) (* TODO statement *) - let* parent_has_ommers := (* TODO expression *) in + do* M.assign "parent_has_ommers" [[ + (* TODO expression *) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* block_difficulty := calculate_block_difficulty (| - header.["number"], - header.["timestamp"], - parent_header.["timestamp"], - parent_header.["difficulty"], - parent_has_ommers - |) in + 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 *) - let* block_parent_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - parent_header - |) - |) in + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in (* TODO statement *) - do* validate_proof_of_work (| + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| header - |) in + |) ]] in + M.pure tt. - -Definition generate_header_hash_for_pow : M unit := +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. @@ -238,11 +261,13 @@ Definition generate_header_hash_for_pow : M unit := hash : `Hash32` The PoW valid rlp hash of the passed in header. *) - let* header_data_without_pow_artefacts := (* TODO expression *) in + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition validate_proof_of_work : M unit := +Definition validate_proof_of_work (header : Header) : M unit := (* Validates the Proof of Work constraints. @@ -257,19 +282,25 @@ Definition validate_proof_of_work : M unit := header : Header of interest. *) - let* header_hash := generate_header_hash_for_pow (| - header - |) in - let* cache := ethereum.ethash.generate_cache (| - header.["number"] - |) in + 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 *) - let* limit := (* TODO expression *) in + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition check_transaction : M unit := +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. @@ -297,15 +328,17 @@ Definition check_transaction : M unit := If the transaction is not includable. *) (* TODO statement *) - let* sender_address := recover_sender (| - chain_id, - tx - |) in + 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 : M unit := +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. @@ -326,13 +359,15 @@ Definition make_receipt : M unit := receipt : The receipt for the transaction. *) - let* receipt := blocks.Receipt (| + do* M.assign "receipt" [[ + blocks.Receipt ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition apply_body : M unit := +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. @@ -375,25 +410,31 @@ Definition apply_body : M unit := apply_body_output : `ApplyBodyOutput` Output of applying the block body to the state. *) - let* gas_available := block_gas_limit in + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - do* pay_rewards (| + do* [[ M.get_local ~(| "pay_rewards" |) ~(| state, block_number, coinbase, ommers - |) in - let* block_gas_used := (* TODO expression *) in - let* block_logs_bloom := bloom.logs_bloom (| - block_logs - |) in - (* TODO statement *) - - -Definition validate_ommers : M unit := + |) ]] 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. @@ -415,23 +456,31 @@ Definition validate_ommers : M unit := chain : History and current state. *) - let* block_hash := rlp.["rlp_hash"] (| - block_header - |) in + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* ommers_hashes := (* TODO expression *) in + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* recent_canonical_blocks := (* TODO expression *) in - let* recent_canonical_block_hashes := (* TODO expression *) in + 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 : M unit := +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. @@ -457,21 +506,25 @@ Definition pay_rewards : M unit := ommers : List of ommers mentioned in the current block. *) - let* ommer_count := ethereum_types.numeric.U256 (| - len (| - ommers - |) - |) in - let* miner_reward := (* TODO expression *) in - do* state.create_ether (| + 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, - miner_reward - |) in + M.get_local ~(| "miner_reward" |) + |) ]] in (* TODO statement *) + M.pure tt. - -Definition process_transaction : M unit := +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := (* Execute a transaction against the provided environment. @@ -499,74 +552,108 @@ Definition process_transaction : M unit := Logs generated during execution. *) (* TODO statement *) - let* sender := env.["origin"] in - let* sender_account := state.get_account (| - env.["state"], - sender - |) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* effective_gas_fee := (* TODO expression *) in - let* gas := (* TODO expression *) in - do* state.increment_nonce (| - env.["state"], - sender - |) in - let* sender_balance_after_gas_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - ethereum_types.numeric.U256 (| - sender_balance_after_gas_fee - |) - |) in - let* preaccessed_addresses := set (| - - |) in - let* preaccessed_storage_keys := set (| - - |) in - (* TODO statement *) - let* message := utils.message.prepare_message (| - sender, - tx.["to"], - tx.["value"], - tx.["data"], - gas, - env - |) in - let* output := vm.interpreter.process_message_call (| - message, - env - |) in - let* gas_used := (* TODO expression *) in - let* gas_refund := min (| - (* TODO expression *), - ethereum_types.numeric.Uint (| - output.["refund_counter"] + 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 - let* gas_refund_amount := (* TODO expression *) in - let* priority_fee_per_gas := (* TODO expression *) in - let* transaction_fee := (* TODO expression *) in - let* total_gas_used := (* TODO expression *) in - let* sender_balance_after_refund := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - sender_balance_after_refund - |) in - let* coinbase_balance_after_mining_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - - -Definition validate_transaction : M unit := + |) ]] 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. @@ -594,9 +681,9 @@ Definition validate_transaction : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition calculate_intrinsic_cost : M unit := +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := (* Calculates the gas that is charged before execution is started. @@ -619,15 +706,19 @@ Definition calculate_intrinsic_cost : M unit := verified : `ethereum.base_types.Uint` The intrinsic cost of the transaction. *) - let* data_cost := (* TODO expression *) in + do* M.assign "data_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) - let* access_list_cost := (* TODO expression *) in + do* M.assign "access_list_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition recover_sender : M unit := +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := (* Extracts the sender address from a transaction. @@ -654,9 +745,9 @@ Definition recover_sender : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_pre155 : M unit := +Definition signing_hash_pre155 (tx : LegacyTransaction) : M Hash32 := (* Compute the hash of a transaction used in a legacy (pre EIP 155) signature. @@ -671,9 +762,9 @@ Definition signing_hash_pre155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_155 : M unit := +Definition signing_hash_155 (tx : LegacyTransaction) (chain_id : U64) : M Hash32 := (* Compute the hash of a transaction used in a EIP 155 signature. @@ -690,9 +781,9 @@ Definition signing_hash_155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_2930 : M unit := +Definition signing_hash_2930 (tx : AccessListTransaction) : M Hash32 := (* Compute the hash of a transaction used in a EIP 2930 signature. @@ -707,9 +798,9 @@ Definition signing_hash_2930 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_1559 : M unit := +Definition signing_hash_1559 (tx : FeeMarketTransaction) : M Hash32 := (* Compute the hash of a transaction used in a EIP 1559 signature. @@ -724,9 +815,9 @@ Definition signing_hash_1559 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition compute_header_hash : M unit := +Definition compute_header_hash (header : Header) : M Hash32 := (* Computes the hash of a block header. @@ -759,9 +850,9 @@ Definition compute_header_hash : M unit := Hash of the header. *) (* TODO statement *) + M.pure tt. - -Definition check_gas_limit : M unit := +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := (* Validates the gas limit for a block. @@ -789,14 +880,16 @@ Definition check_gas_limit : M unit := check : `bool` True if gas limit constraints are satisfied, False otherwise. *) - let* max_adjustment_delta := (* TODO expression *) in + 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 : M unit := +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. @@ -835,9 +928,15 @@ Definition calculate_block_difficulty : M unit := difficulty : `ethereum.base_types.Uint` Computed difficulty for a block. *) - let* offset := (* TODO expression *) in - let* difficulty := (* TODO expression *) in - let* num_bomb_periods := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - + 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.v b/coq/ethereum/london/fork_types.v index 14de99d5e5..d84cffdf45 100644 --- a/coq/ethereum/london/fork_types.v +++ b/coq/ethereum/london/fork_types.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Types ^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. +Require ethereum.__init__. +Require ethereum.crypto.hash. -Definition encode_account : M unit := +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := (* Encode `Account` dataclass. @@ -26,4 +28,4 @@ Definition encode_account : M unit := encoded without providing a storage root. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/london/state.v b/coq/ethereum/london/state.v index 007b01e85f..924a374914 100644 --- a/coq/ethereum/london/state.v +++ b/coq/ethereum/london/state.v @@ -1,3 +1,4 @@ +(* Generated *) (* State ^^^^^ @@ -22,10 +23,10 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require london.fork_types. -Require london.trie. +Require ethereum.london.fork_types. +Require ethereum.london.trie. -Definition close_state : M unit := +Definition close_state (state : State) : M unit := (* Free resources held by the state. Used by optimized implementations to release file descriptors. @@ -34,9 +35,9 @@ Definition close_state : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition begin_transaction : M unit := +Definition begin_transaction (state : State) : M unit := (* Start a state transaction. @@ -48,12 +49,12 @@ Definition begin_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition commit_transaction : M unit := +Definition commit_transaction (state : State) : M unit := (* Commit a state transaction. @@ -62,13 +63,13 @@ Definition commit_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["pop"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition rollback_transaction : M unit := +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. @@ -80,9 +81,9 @@ Definition rollback_transaction : M unit := *) (* TODO assignment *) (* TODO statement *) + M.pure tt. - -Definition get_account : M unit := +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. @@ -102,14 +103,16 @@ Definition get_account : M unit := account : `Account` Account at address. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition get_account_optional : M unit := +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. @@ -126,14 +129,16 @@ Definition get_account_optional : M unit := account : `Account` Account at address. *) - let* account := trie.trie_get (| - state.["_main_trie"], - address - |) in + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition set_account : M unit := +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()`). @@ -147,14 +152,14 @@ Definition set_account : M unit := account : `Account` Account to set at address. *) - do* trie.trie_set (| - state.["_main_trie"], + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), address, account - |) in + |) ]] in + M.pure tt. - -Definition destroy_account : M unit := +Definition destroy_account (state : State) (address : Address) : M unit := (* Completely remove the account at `address` and all of its storage. @@ -169,18 +174,18 @@ Definition destroy_account : M unit := address : `Address` Address of account to destroy. *) - do* destroy_storage (| + do* [[ M.get_local ~(| "destroy_storage" |) ~(| state, address - |) in - do* set_account (| + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - (* TODO expression *) - |) in + tt + |) ]] in + M.pure tt. - -Definition destroy_storage : M unit := +Definition destroy_storage (state : State) (address : Address) : M unit := (* Completely remove the storage at `address`. @@ -192,9 +197,9 @@ Definition destroy_storage : M unit := Address of account whose storage is to be deleted. *) (* TODO statement *) + M.pure tt. - -Definition mark_account_created : M unit := +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 @@ -211,12 +216,12 @@ Definition mark_account_created : M unit := address : `Address` Address of the account that has been created. *) - do* state.["created_accounts"].["add"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| address - |) in - + |) ]] in + M.pure tt. -Definition get_storage : M unit := +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. @@ -235,19 +240,23 @@ Definition get_storage : M unit := value : `U256` Value at the key. *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition set_storage : M unit := +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. @@ -264,19 +273,21 @@ Definition set_storage : M unit := Value to set at the key. *) (* TODO statement *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - do* trie.trie_set (| - trie, + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), key, value - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition storage_root : M unit := +Definition storage_root (state : State) (address : Address) : M Root := (* Calculate the storage root of an account. @@ -294,9 +305,9 @@ Definition storage_root : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition state_root : M unit := +Definition state_root (state : State) : M Root := (* Calculate the state root. @@ -313,9 +324,9 @@ Definition state_root : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition account_exists : M unit := +Definition account_exists (state : State) (address : Address) : M bool := (* Checks if an account exists in the state trie @@ -332,9 +343,9 @@ Definition account_exists : M unit := True if account exists in the state trie, False otherwise *) (* TODO statement *) + M.pure tt. - -Definition account_has_code_or_nonce : M unit := +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := (* Checks if an account has non zero nonce or non empty code @@ -351,14 +362,16 @@ Definition account_has_code_or_nonce : M unit := True if if an account has non zero nonce or non empty code, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_empty : M unit := +Definition is_account_empty (state : State) (address : Address) : M bool := (* Checks if an account has zero nonce, empty code and zero balance. @@ -375,14 +388,16 @@ Definition is_account_empty : M unit := True if if an account has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition account_exists_and_is_empty : M unit := +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. @@ -400,14 +415,16 @@ Definition account_exists_and_is_empty : M unit := True if an account exists and has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_alive : M unit := +Definition is_account_alive (state : State) (address : Address) : M bool := (* Check whether is an account is both in the state and non empty. @@ -423,49 +440,51 @@ Definition is_account_alive : M unit := is_alive : `bool` True if the account is alive. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition modify_state : M unit := +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := (* Modify an `Account` in the `State`. *) - do* set_account (| + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - ethereum_types.frozen.modify (| - get_account (| + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| state, address |), f |) - |) in - + |) ]] in + M.pure tt. -Definition move_ether : M unit := +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := (* Move funds between accounts. *) (* TODO statement *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, sender_address, - reduce_sender_balance - |) in - do* modify_state (| + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| state, recipient_address, - increase_recipient_balance - |) in - + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. -Definition set_account_balance : M unit := +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := (* Sets the balance of an account. @@ -481,14 +500,14 @@ Definition set_account_balance : M unit := The amount that needs to set in balance. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - set_balance - |) in + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. - -Definition touch_account : M unit := +Definition touch_account (state : State) (address : Address) : M unit := (* Initializes an account to state. @@ -501,9 +520,9 @@ Definition touch_account : M unit := The address of the account that need to initialised. *) (* TODO statement *) + M.pure tt. - -Definition increment_nonce : M unit := +Definition increment_nonce (state : State) (address : Address) : M unit := (* Increments the nonce of an account. @@ -516,14 +535,14 @@ Definition increment_nonce : M unit := Address of the account whose nonce needs to be incremented. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_nonce - |) in + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. - -Definition set_code : M unit := +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := (* Sets Account code. @@ -539,14 +558,14 @@ Definition set_code : M unit := The bytecode that needs to be set. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - write_code - |) in - + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. -Definition create_ether : M unit := +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := (* Add newly created ether to an account. @@ -560,14 +579,14 @@ Definition create_ether : M unit := The amount of ether to be added to the account of interest. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_balance - |) in - + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. -Definition get_storage_original : M unit := +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 @@ -584,10 +603,12 @@ Definition get_storage_original : M unit := *) (* TODO statement *) (* TODO assignment *) - let* original_account_trie := original_trie.["get"] (| - address - |) in + 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.v b/coq/ethereum/london/transactions.v index 8c84a4032a..94a6572eb2 100644 --- a/coq/ethereum/london/transactions.v +++ b/coq/ethereum/london/transactions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, @@ -9,19 +10,20 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require london.exceptions. -Require london.fork_types. +Require ethereum.__init__. +Require ethereum.london.exceptions. +Require ethereum.london.fork_types. -Definition encode_transaction : M unit := +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 : M unit := +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.v b/coq/ethereum/london/trie.v index 548de91e1c..6b8953f256 100644 --- a/coq/ethereum/london/trie.v +++ b/coq/ethereum/london/trie.v @@ -1,3 +1,4 @@ +(* Generated *) (* State Trie ^^^^^^^^^^ @@ -14,7 +15,7 @@ The state trie is the structure responsible for storing *) -Definition encode_internal_node : M unit := +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 @@ -35,22 +36,24 @@ Definition encode_internal_node : M unit := *) (* TODO statement *) (* TODO statement *) - let* encoded := rlp.["encode"] (| - unencoded - |) in + 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 : M unit := +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 : M unit := +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. @@ -66,9 +69,9 @@ Definition copy_trie : M unit := A copy of the trie. *) (* TODO statement *) + M.pure tt. - -Definition trie_set : M unit := +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := (* Stores an item in a Merkle Trie. @@ -85,9 +88,9 @@ Definition trie_set : M unit := Node to insert at `key`. *) (* TODO statement *) + M.pure tt. - -Definition trie_get : M unit := +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := (* Gets an item from the Merkle Trie. @@ -106,17 +109,17 @@ Definition trie_get : M unit := Node at `key` in the trie. *) (* TODO statement *) + M.pure tt. - -Definition common_prefix_length : M unit := +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 : M unit := +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := (* Compresses nibble-list into a standard byte array with a flag. @@ -150,14 +153,16 @@ Definition nibble_list_to_compact : M unit := compressed : `bytearray` Compact byte array. *) - let* compact := bytearray (| + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition bytes_to_nibble_list : M unit := +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := (* Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). @@ -171,14 +176,16 @@ Definition bytes_to_nibble_list : M unit := nibble_list : `Bytes` The `Bytes` in nibble-list format. *) - let* nibble_list := bytearray (| - (* TODO expression *) - |) in + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _prepare_trie : M unit := +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. @@ -199,9 +206,9 @@ Definition _prepare_trie : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition root : M unit := +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := (* Computes the root of a modified merkle patricia trie (MPT). @@ -219,22 +226,26 @@ Definition root : M unit := root : `.fork_types.Root` MPT root of the underlying key-value pairs. *) - let* obj := _prepare_trie (| - trie, - get_storage_root - |) in - let* root_node := encode_internal_node (| - patricialize (| - obj, - Uint (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) + M.pure tt. - -Definition patricialize : M unit := +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := (* Structural composition function. @@ -254,21 +265,29 @@ Definition patricialize : M unit := Root node of `obj`. *) (* TODO statement *) - let* arbitrary_key := next (| - iter (| - obj - |) - |) in + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in (* TODO statement *) - let* substring := (* TODO expression *) in - let* prefix_length := len (| - substring - |) in + 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 *) - let* value := (* TODO expression *) in + do* M.assign "value" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/london/utils/__init__.v b/coq/ethereum/london/utils/__init__.v index beff4482b1..7f30fe939b 100644 --- a/coq/ethereum/london/utils/__init__.v +++ b/coq/ethereum/london/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions unique to this particular fork. *) diff --git a/coq/ethereum/london/utils/address.v b/coq/ethereum/london/utils/address.v index c250f51fe7..d258fab837 100644 --- a/coq/ethereum/london/utils/address.v +++ b/coq/ethereum/london/utils/address.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,9 +19,10 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require london.fork_types. +Require ethereum.__init__. +Require ethereum.london.fork_types. -Definition to_address : M unit := +Definition to_address (data : (* TODO type *)) : M Address := (* Convert a Uint or U256 value to a valid address (20 bytes). @@ -35,9 +37,9 @@ Definition to_address : M unit := The obtained address. *) (* TODO statement *) + M.pure tt. - -Definition compute_contract_address : M unit := +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := (* Computes address of the new account that needs to be created. @@ -54,20 +56,26 @@ Definition compute_contract_address : M unit := address: `Address` The computed address of the new account. *) - let* computed_address := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *) - |) - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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 : M unit := +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. @@ -86,14 +94,22 @@ Definition compute_create2_contract_address : M unit := address: `ethereum.london.fork_types.Address` The computed address of the new account. *) - let* preimage := (* TODO expression *) in - let* computed_address := ethereum.crypto.hash.keccak256 (| - preimage - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/london/utils/hexadecimal.v index d606b6a6db..61730ba174 100644 --- a/coq/ethereum/london/utils/hexadecimal.v +++ b/coq/ethereum/london/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ London types. *) Require ethereum.utils.hexadecimal. -Require london.fork_types. +Require ethereum.london.fork_types. -Definition hex_to_root : M unit := +Definition hex_to_root (hex_string : str) : M Root := (* Convert hex string to trie root. @@ -31,9 +32,9 @@ Definition hex_to_root : M unit := Trie root obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bloom : M unit := +Definition hex_to_bloom (hex_string : str) : M Bloom := (* Convert hex string to bloom. @@ -48,9 +49,9 @@ Definition hex_to_bloom : M unit := Bloom obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_address : M unit := +Definition hex_to_address (hex_string : str) : M Address := (* Convert hex string to Address (20 bytes). @@ -65,4 +66,4 @@ Definition hex_to_address : M unit := The address obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/london/utils/message.v b/coq/ethereum/london/utils/message.v index feedd4deef..56215e8a73 100644 --- a/coq/ethereum/london/utils/message.v +++ b/coq/ethereum/london/utils/message.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For The Message Data-structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,13 +17,13 @@ specification. Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require london.fork_types. -Require london.state. -Require london.vm. -Require london.vm.precompiled_contracts.mapping. -Require london.utils.address. +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 : M unit := +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. @@ -61,22 +62,24 @@ Definition prepare_message : M unit := Items containing contract creation or message call specific data. *) (* TODO statement *) - let* accessed_addresses := set (| + do* M.assign "accessed_addresses" [[ + M.get_local ~(| "set" |) ~(| - |) in - do* accessed_addresses.["add"] (| - current_target - |) in - do* accessed_addresses.["add"] (| + |) 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* accessed_addresses.["update"] (| - vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS.["keys"] (| + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS, "keys" |) ~(| |) - |) in - do* accessed_addresses.["update"] (| + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| preaccessed_addresses - |) in + |) ]] in (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/london/vm/__init__.v b/coq/ethereum/london/vm/__init__.v index a97b0b379a..c17fd4816f 100644 --- a/coq/ethereum/london/vm/__init__.v +++ b/coq/ethereum/london/vm/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,12 +19,12 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require london.blocks. -Require london.fork_types. -Require london.state. -Require london.vm.precompiled_contracts. +Require ethereum.london.blocks. +Require ethereum.london.fork_types. +Require ethereum.london.state. +Require ethereum.london.vm.precompiled_contracts. -Definition incorporate_child_on_success : M unit := +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of a successful `child_evm` into the parent `evm`. @@ -34,25 +35,31 @@ Definition incorporate_child_on_success : M unit := 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 *) - (* TODO statement *) - (* TODO statement *) - do* evm.["accounts_to_delete"].["update"] (| - child_evm.["accounts_to_delete"] - |) in - do* evm.["touched_accounts"].["update"] (| - child_evm.["touched_accounts"] - |) in - (* TODO statement *) - do* evm.["accessed_addresses"].["update"] (| - child_evm.["accessed_addresses"] - |) in - do* evm.["accessed_storage_keys"].["update"] (| - child_evm.["accessed_storage_keys"] - |) in + 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 : M unit := +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. @@ -65,5 +72,7 @@ Definition incorporate_child_on_error : M unit := *) (* TODO statement *) (* 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.v b/coq/ethereum/london/vm/exceptions.v index 1784494410..47e26555d5 100644 --- a/coq/ethereum/london/vm/exceptions.v +++ b/coq/ethereum/london/vm/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Exceptions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/london/vm/gas.v b/coq/ethereum/london/vm/gas.v index 50f82cfa20..d43f8161ea 100644 --- a/coq/ethereum/london/vm/gas.v +++ b/coq/ethereum/london/vm/gas.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Gas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,9 +18,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.trace. Require ethereum.utils.numeric. -Require london.vm.exceptions. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.exceptions. -Definition charge_gas : M unit := +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := (* Subtracts `amount` from `evm.gas_left`. @@ -31,18 +33,18 @@ Definition charge_gas : M unit := The amount of gas the current operation requires. *) - do* ethereum.trace.evm_trace (| + do* [[ ethereum.trace.evm_trace ~(| evm, - ethereum.trace.GasAndRefund (| - int (| + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| amount |) |) - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_memory_gas_cost : M unit := +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, @@ -58,14 +60,22 @@ Definition calculate_memory_gas_cost : M unit := total_gas_cost : `ethereum.base_types.Uint` The gas cost for storing data in memory. *) - let* size_in_words := (* TODO expression *) in - let* linear_cost := (* TODO expression *) in - let* quadratic_cost := (* TODO expression *) in - let* total_gas_cost := (* TODO expression *) in + 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 : M unit := +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := (* Calculates the gas amount to extend memory @@ -81,22 +91,28 @@ Definition calculate_gas_extend_memory : M unit := ------- extend_memory: `ExtendMemory` *) - let* size_to_extend := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* to_be_paid := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* current_size := ethereum_types.numeric.Uint (| - len (| - memory - |) - |) in + 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 : M unit := +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. @@ -122,18 +138,22 @@ Definition calculate_message_call_gas : M unit := ------- message_call_gas: `MessageCallGas` *) - let* call_stipend := (* TODO expression *) in + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* gas := min (| - gas, - max_message_call_gas (| - (* TODO expression *) - |) - |) in + 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 : M unit := +Definition max_message_call_gas (gas : Uint) : M Uint := (* Calculates the maximum gas that is allowed for making a message call @@ -148,4 +168,4 @@ Definition max_message_call_gas : M unit := The maximum gas allowed for making the message-call. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/london/vm/instructions/__init__.v b/coq/ethereum/london/vm/instructions/__init__.v index b36b1ebfef..cbd7e7e63a 100644 --- a/coq/ethereum/london/vm/instructions/__init__.v +++ b/coq/ethereum/london/vm/instructions/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* EVM Instruction Encoding (Opcodes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/london/vm/instructions/arithmetic.v b/coq/ethereum/london/vm/instructions/arithmetic.v index f0724740f9..d063a4b96d 100644 --- a/coq/ethereum/london/vm/instructions/arithmetic.v +++ b/coq/ethereum/london/vm/instructions/arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,11 @@ Implementations of the EVM Arithmetic instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require london.vm.gas. -Require london.vm.stack. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.stack. -Definition add : M unit := +Definition add (evm : Evm) : M unit := (* Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -28,27 +30,37 @@ Definition add : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_add"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sub (evm : Evm) : M unit := (* Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -59,27 +71,37 @@ Definition sub : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_sub"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mul (evm : Evm) : M unit := (* Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -90,27 +112,37 @@ Definition mul : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_mul"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition div (evm : Evm) : M unit := (* Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -121,25 +153,33 @@ Definition div : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |) in - let* divisor := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - quotient - |) 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 : M unit := +Definition sdiv (evm : Evm) : M unit := (* Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -150,31 +190,39 @@ Definition sdiv : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* divisor := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - quotient + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mod : M unit := +Definition mod (evm : Evm) : M unit := (* Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -185,25 +233,33 @@ Definition mod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - remainder - |) in + |) ]] 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 : M unit := +Definition smod (evm : Evm) : M unit := (* Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -214,31 +270,39 @@ Definition smod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* y := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - remainder + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition addmod : M unit := +Definition addmod (evm : Evm) : M unit := (* Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -249,34 +313,44 @@ Definition addmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +Definition mulmod (evm : Evm) : M unit := (* Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -287,34 +361,44 @@ Definition mulmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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 : M unit := +Definition exp (evm : Evm) : M unit := (* Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -325,39 +409,53 @@ Definition exp : M unit := The current EVM frame. *) - let* base := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent_bits := exponent.["bit_length"] (| - - |) in - let* exponent_bytes := (* TODO expression *) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - pow (| - base, - exponent, - (* 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 - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition signextend : M unit := +Definition signextend (evm : Evm) : M unit := (* Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -368,20 +466,28 @@ Definition signextend : M unit := The current EVM frame. *) - let* byte_num := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/london/vm/instructions/bitwise.v index dfc5f29532..7768d2fde4 100644 --- a/coq/ethereum/london/vm/instructions/bitwise.v +++ b/coq/ethereum/london/vm/instructions/bitwise.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Bitwise Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM bitwise instructions. *) Require ethereum_types.numeric. -Require london.vm.gas. -Require london.vm.stack. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.stack. -Definition bitwise_and : M unit := +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. @@ -27,24 +29,32 @@ Definition bitwise_and : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_or : M unit := +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. @@ -55,24 +65,32 @@ Definition bitwise_or : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_xor : M unit := +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. @@ -83,24 +101,32 @@ Definition bitwise_xor : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_not : M unit := +Definition bitwise_not (evm : Evm) : M unit := (* Bitwise NOT operation of the top element of the stack. Pushes the result back on the stack. @@ -111,21 +137,27 @@ Definition bitwise_not : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition get_byte : M unit := +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 @@ -137,25 +169,33 @@ Definition get_byte : M unit := The current EVM frame. *) - let* byte_index := stack.pop (| - evm.["stack"] - |) in - let* word := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -164,29 +204,37 @@ Definition bitwise_shl : M unit := evm : The current EVM frame. *) - let* shift := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -195,25 +243,33 @@ Definition bitwise_shr : M unit := evm : The current EVM frame. *) - let* shift := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -222,24 +278,32 @@ Definition bitwise_sar : M unit := evm : The current EVM frame. *) - let* shift := int (| - stack.pop (| - evm.["stack"] - |) - |) in - let* signed_value := stack.pop (| - evm.["stack"] - |).["to_signed"] (| + 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 - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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.v b/coq/ethereum/london/vm/instructions/block.v index 4906386fc4..e4a1c93552 100644 --- a/coq/ethereum/london/vm/instructions/block.v +++ b/coq/ethereum/london/vm/instructions/block.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Block Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM block instructions. *) Require ethereum_types.numeric. -Require london.vm.gas. -Require london.vm.stack. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.stack. -Definition block_hash : M unit := +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. @@ -27,27 +29,35 @@ Definition block_hash : M unit := The current EVM frame. *) - let* block_number := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* max_block_number := (* TODO expression *) in + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition coinbase : M unit := +Definition coinbase (evm : Evm) : M unit := (* Push the current block's beneficiary address (address of the block miner) onto the stack. @@ -62,20 +72,24 @@ Definition coinbase : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["coinbase"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition timestamp : M unit := +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. @@ -90,18 +104,22 @@ Definition timestamp : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["env"].["time"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition number (evm : Evm) : M unit := (* Push the current block's number onto the stack. @@ -115,20 +133,24 @@ Definition number : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["number"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition difficulty : M unit := +Definition difficulty (evm : Evm) : M unit := (* Push the current block's difficulty onto the stack. @@ -142,20 +164,24 @@ Definition difficulty : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["difficulty"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_limit : M unit := +Definition gas_limit (evm : Evm) : M unit := (* Push the current block's gas limit onto the stack. @@ -169,20 +195,24 @@ Definition gas_limit : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_limit"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition chain_id : M unit := +Definition chain_id (evm : Evm) : M unit := (* Push the chain id onto the stack. @@ -193,15 +223,19 @@ Definition chain_id : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["chain_id"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/london/vm/instructions/comparison.v index 7d4dbaedc0..996662ec08 100644 --- a/coq/ethereum/london/vm/instructions/comparison.v +++ b/coq/ethereum/london/vm/instructions/comparison.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Comparison Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM Comparison instructions. *) Require ethereum_types.numeric. -Require london.vm.gas. -Require london.vm.stack. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.stack. -Definition less_than : M unit := +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. @@ -27,27 +29,37 @@ Definition less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_less_than : M unit := + |) ]] 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. @@ -57,31 +69,41 @@ Definition signed_less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition greater_than : M unit := + |) ]] 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. @@ -92,27 +114,37 @@ Definition greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_greater_than : M unit := + |) ]] 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. @@ -122,31 +154,41 @@ Definition signed_greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition equal : M unit := + |) ]] 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. @@ -157,27 +199,37 @@ Definition equal : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition is_zero : M unit := + |) ]] 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. @@ -188,19 +240,27 @@ Definition is_zero : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/london/vm/instructions/control_flow.v index 50a0957f1d..3355af2430 100644 --- a/coq/ethereum/london/vm/instructions/control_flow.v +++ b/coq/ethereum/london/vm/instructions/control_flow.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Control Flow Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM control flow instructions. *) Require ethereum_types.numeric. -Require london.vm.gas. -Require london.vm.exceptions. -Require london.vm.stack. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.exceptions. +Require ethereum.london.vm.stack. -Definition stop : M unit := +Definition stop (evm : Evm) : M unit := (* Stop further execution of EVM code. @@ -29,10 +31,14 @@ Definition stop : M unit := (* TODO statement *) (* TODO statement *) (* TODO assignment *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jump : M unit := +Definition jump (evm : Evm) : M unit := (* Alter the program counter to the location specified by the top of the stack. @@ -43,20 +49,22 @@ Definition jump : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition jumpi : M unit := +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 @@ -68,23 +76,27 @@ Definition jumpi : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* conditional_value := stack.pop (| - evm.["stack"] - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition pc : M unit := +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. @@ -96,20 +108,24 @@ Definition pc : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["pc"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_left : M unit := +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. @@ -121,20 +137,24 @@ Definition gas_left : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["gas_left"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jumpdest : M unit := +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 @@ -147,10 +167,14 @@ Definition jumpdest : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_JUMPDEST - |) in - (* TODO statement *) + |) ]] 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.v b/coq/ethereum/london/vm/instructions/environment.v index 530a443045..20b6c36c3f 100644 --- a/coq/ethereum/london/vm/instructions/environment.v +++ b/coq/ethereum/london/vm/instructions/environment.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,15 +16,16 @@ Implementations of the EVM environment related instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require london.fork_types. -Require london.state. -Require london.utils.address. -Require london.vm.memory. -Require london.vm.exceptions. -Require london.vm.gas. -Require london.vm.stack. - -Definition address : M unit := +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. @@ -34,20 +36,24 @@ Definition address : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["current_target"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition balance : M unit := +Definition balance (evm : Evm) : M unit := (* Pushes the balance of the given account onto the stack. @@ -57,24 +63,32 @@ Definition balance : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] + 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 - (* TODO statement *) - let* balance := state.get_account (| - evm.["env"].["state"], - address - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition origin : M unit := +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. @@ -86,20 +100,24 @@ Definition origin : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["origin"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition caller : M unit := +Definition caller (evm : Evm) : M unit := (* Pushes the address of the caller onto the stack. @@ -110,20 +128,24 @@ Definition caller : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["caller"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition callvalue : M unit := +Definition callvalue (evm : Evm) : M unit := (* Push the value (in wei) sent with the call onto the stack. @@ -134,18 +156,22 @@ Definition callvalue : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["message"].["value"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition calldataload (evm : Evm) : M unit := (* Push a word (32 bytes) of the input data belonging to the current environment onto the stack. @@ -156,30 +182,38 @@ Definition calldataload : M unit := The current EVM frame. *) - let* start_index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - start_index, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] 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* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - value + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 |) - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition calldatasize : M unit := +Definition calldatasize (evm : Evm) : M unit := (* Push the size of input data in current environment onto the stack. @@ -190,22 +224,26 @@ Definition calldatasize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["message"].["data"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition calldatacopy : M unit := +Definition calldatacopy (evm : Evm) : M unit := (* Copy a portion of the input data in current environment to memory. @@ -218,40 +256,60 @@ Definition calldatacopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* data_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - data_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition codesize (evm : Evm) : M unit := (* Push the size of code running in current environment onto the stack. @@ -262,22 +320,26 @@ Definition codesize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["code"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition codecopy : M unit := +Definition codecopy (evm : Evm) : M unit := (* Copy a portion of the code in current environment to memory. @@ -290,40 +352,60 @@ Definition codecopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["code"], - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition gasprice (evm : Evm) : M unit := (* Push the gas price used in current environment onto the stack. @@ -334,20 +416,24 @@ Definition gasprice : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_price"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition extcodesize : M unit := +Definition extcodesize (evm : Evm) : M unit := (* Push the code size of a given account onto the stack. @@ -357,28 +443,36 @@ Definition extcodesize : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - (* TODO statement *) - let* codesize := ethereum_types.numeric.U256 (| - len (| - state.get_account (| - evm.["env"].["state"], - address - |).["code"] + 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 - do* stack.push (| - evm.["stack"], - codesize - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition extcodecopy : M unit := +Definition extcodecopy (evm : Evm) : M unit := (* Copy a portion of an account's code to memory. @@ -388,46 +482,70 @@ Definition extcodecopy : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - (* TODO statement *) - let* code := state.get_account (| - evm.["env"].["state"], - address - |).["code"] in - let* value := vm.memory.buffer_read (| - code, - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in + 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 : M unit := +Definition returndatasize (evm : Evm) : M unit := (* Pushes the size of the return data buffer onto the stack. @@ -437,22 +555,26 @@ Definition returndatasize : M unit := The current EVM frame. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["return_data"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition returndatacopy : M unit := +Definition returndatacopy (evm : Evm) : M unit := (* Copies data from the return data buffer code to memory @@ -461,37 +583,57 @@ Definition returndatacopy : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* return_data_start_position := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - (* TODO statement *) - let* value := (* TODO expression *) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in + |) ]] 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 : M unit := +Definition extcodehash (evm : Evm) : M unit := (* Returns the keccak256 hash of a contract’s bytecode Parameters @@ -499,25 +641,33 @@ Definition extcodehash : M unit := evm : The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] + 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 - (* TODO statement *) - let* account := state.get_account (| - evm.["env"].["state"], - address - |) in - (* TODO statement *) - do* stack.push (| - evm.["stack"], - codehash - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition self_balance : M unit := +Definition self_balance (evm : Evm) : M unit := (* Pushes the balance of the current address to the stack. @@ -528,22 +678,28 @@ Definition self_balance : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_FAST_STEP - |) in - let* balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition base_fee (evm : Evm) : M unit := (* Pushes the base fee of the current block on to the stack. @@ -554,15 +710,19 @@ Definition base_fee : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["base_fee_per_gas"] + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/london/vm/instructions/keccak.v index 1a59188d7c..e03f22a1fc 100644 --- a/coq/ethereum/london/vm/instructions/keccak.v +++ b/coq/ethereum/london/vm/instructions/keccak.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Keccak Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM keccak instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require london.vm.gas. -Require london.vm.memory. -Require london.vm.stack. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.memory. +Require ethereum.london.vm.stack. -Definition keccak : M unit := +Definition keccak (evm : Evm) : M unit := (* Pushes to the stack the Keccak-256 hash of a region of memory. @@ -32,36 +34,56 @@ Definition keccak : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* word_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in - let* hash := ethereum.crypto.hash.keccak256 (| - data - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/london/vm/instructions/log.v index 71e198ec76..737e1cd8b1 100644 --- a/coq/ethereum/london/vm/instructions/log.v +++ b/coq/ethereum/london/vm/instructions/log.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Logging Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,13 +15,14 @@ Implementations of the EVM logging instructions. Require functools. Require ethereum_types.numeric. -Require london.blocks. -Require london.vm.exceptions. -Require london.vm.gas. -Require london.vm.memory. -Require london.vm.stack. +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 : M unit := +Definition log_n (evm : Evm) (num_topics : U256) : M unit := (* Appends a log entry, having `num_topics` topics, to the evm logs. @@ -35,27 +37,43 @@ Definition log_n : M unit := The number of topics to be included in the log entry. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* topics := (* TODO expression *) in + 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 *) - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in (* TODO statement *) - let* log_entry := blocks.Log (| + do* M.assign "log_entry" [[ + blocks.Log ~(| - |) in + |) in + ]] in (* TODO assignment *) - (* 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/memory.v b/coq/ethereum/london/vm/instructions/memory.v index f3b36dd756..66ae2a82e0 100644 --- a/coq/ethereum/london/vm/instructions/memory.v +++ b/coq/ethereum/london/vm/instructions/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM Memory instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require london.vm.gas. -Require london.vm.memory. -Require london.vm.stack. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.memory. +Require ethereum.london.vm.stack. -Definition mstore : M unit := +Definition mstore (evm : Evm) : M unit := (* Stores a word to memory. This also expands the memory, if the memory is @@ -30,32 +32,44 @@ Definition mstore : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* memory.memory_write (| - evm.["memory"], - start_position, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mstore8 (evm : Evm) : M unit := (* Stores a byte to memory. This also expands the memory, if the memory is @@ -67,33 +81,47 @@ Definition mstore8 : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ (* TODO expression *) - |) in - do* memory.memory_write (| - evm.["memory"], - start_position, - normalized_bytes_value - |) in - (* TODO statement *) - + ]] 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 : M unit := +Definition mload (evm : Evm) : M unit := (* Load word from memory. @@ -103,35 +131,47 @@ Definition mload : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.memory_read_bytes (| - evm.["memory"], - start_position, - ethereum_types.numeric.U256 (| - (* 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 - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition msize : M unit := +Definition msize (evm : Evm) : M unit := (* Push the size of active memory in bytes onto the stack. @@ -142,17 +182,21 @@ Definition msize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["memory"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/london/vm/instructions/stack.v index ea6ac0ddc8..978d31e276 100644 --- a/coq/ethereum/london/vm/instructions/stack.v +++ b/coq/ethereum/london/vm/instructions/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM stack related instructions. Require functools. Require ethereum_types.numeric. -Require london.vm.exceptions. -Require london.vm.gas. -Require london.vm.memory. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.exceptions. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.memory. -Definition pop : M unit := +Definition pop (evm : Evm) : M unit := (* Remove item from stack. @@ -28,18 +30,22 @@ Definition pop : M unit := The current EVM frame. *) - do* stack.["pop"] (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in + |) ]] in (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition push_n : M unit := +Definition push_n (evm : Evm) (num_bytes : int) : M unit := (* Pushes a N-byte immediate onto the stack. @@ -54,29 +60,33 @@ Definition push_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - evm.["code"], - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - num_bytes + |) ]] 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 - do* stack.["push"] (| - evm.["stack"], - data_to_push - |) in - (* TODO statement *) - - -Definition dup_n : M unit := + |) 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. @@ -91,20 +101,26 @@ Definition dup_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - let* data_to_duplicate := (* TODO expression *) in - do* stack.["push"] (| - evm.["stack"], - data_to_duplicate - |) 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 : M unit := +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. @@ -123,11 +139,15 @@ Definition swap_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - (* 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/storage.v b/coq/ethereum/london/vm/instructions/storage.v index ca5c047075..3af6be38e8 100644 --- a/coq/ethereum/london/vm/instructions/storage.v +++ b/coq/ethereum/london/vm/instructions/storage.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Storage Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,12 +14,13 @@ Implementations of the EVM storage related instructions. *) Require ethereum_types.numeric. -Require london.state. -Require london.vm.exceptions. -Require london.vm.gas. -Require london.vm.stack. +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 : M unit := +Definition sload (evm : Evm) : M unit := (* Loads to the stack, the value corresponding to a certain key from the storage of the current account. @@ -29,25 +31,33 @@ Definition sload : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in + |) in + ]] in (* TODO statement *) - let* value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) 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 : M unit := +Definition sstore (evm : Evm) : M unit := (* Stores a value at a certain key in the current context's storage. @@ -57,41 +67,55 @@ Definition sstore : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in (* TODO statement *) - let* original_value := state.get_storage_original (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - let* current_value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - let* gas_cost := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in + M.get_local ~(| "gas_cost" |) + |) ]] in (* TODO statement *) - do* state.set_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key, - new_value - |) 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.v b/coq/ethereum/london/vm/instructions/system.v index cf16568388..e55d0db7e8 100644 --- a/coq/ethereum/london/vm/instructions/system.v +++ b/coq/ethereum/london/vm/instructions/system.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) System Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,57 +16,72 @@ Implementations of the EVM system related instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require london.fork_types. -Require london.state. -Require london.utils.address. -Require london.vm.exceptions. -Require london.vm.gas. -Require london.vm.memory. -Require london.vm.stack. - -Definition generic_create : M unit := +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* evm.["accessed_addresses"].["add"] (| + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "add" |) ~(| contract_address - |) in - let* create_message_gas := gas.max_message_call_gas (| - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |) - |) in - (* TODO statement *) + |) ]] 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 *) - let* sender_address := evm.["message"].["current_target"] in - let* sender := state.get_account (| - evm.["env"].["state"], - sender_address - |) in - (* TODO statement *) - (* TODO statement *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) in - do* state.increment_nonce (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |) in - let* child_message := Message (| - - |) in - let* child_evm := process_create_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - - -Definition create : M unit := + 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. @@ -74,42 +90,58 @@ Definition create : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_contract_address (| - evm.["message"].["current_target"], - state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["nonce"] - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition create2 (evm : Evm) : M unit := (* Creates a new account with associated code. @@ -121,50 +153,70 @@ Definition create2 : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* salt := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* call_data_words := (* TODO expression *) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_create2_contract_address (| - evm.["message"].["current_target"], - salt, - memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size - |) in - (* TODO statement *) - + 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_ : M unit := +Definition return_ (evm : Evm) : M unit := (* Halts execution returning output data. @@ -173,66 +225,84 @@ Definition return_ : M unit := evm : The current EVM frame. *) - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) + |) ]] 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 : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_input_start_position, - memory_input_size - |) in - let* code := state.get_account (| - evm.["env"].["state"], - code_address - |).["code"] in - let* child_message := Message (| - - |) in - let* child_evm := process_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - let* actual_output_size := min (| - memory_output_size, - ethereum_types.numeric.U256 (| - len (| - child_evm.["output"] + 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 - do* memory.memory_write (| - evm.["memory"], + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), memory_output_start_position, (* TODO expression *) - |) in + |) ]] in + M.pure tt. - -Definition call : M unit := +Definition call (evm : Evm) : M unit := (* Message-call into an account. @@ -241,62 +311,92 @@ Definition call : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* create_gas_cost := (* TODO expression *) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition callcode (evm : Evm) : M unit := (* Message-call into this account with alternative account’s code. @@ -305,61 +405,91 @@ Definition callcode : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* to := evm.["message"].["current_target"] in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) - (* TODO statement *) - + |) ]] 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 : M unit := +Definition selfdestruct (evm : Evm) : M unit := (* Halt execution and register account for later deletion. @@ -368,49 +498,59 @@ Definition selfdestruct : M unit := evm : The current EVM frame. *) - let* beneficiary := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* gas_cost := gas.GAS_SELF_DESTRUCT in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - (* TODO statement *) - let* originator := evm.["message"].["current_target"] in - let* beneficiary_balance := state.get_account (| - evm.["env"].["state"], - beneficiary - |).["balance"] in - let* originator_balance := state.get_account (| - evm.["env"].["state"], - originator - |).["balance"] in - do* state.set_account_balance (| - evm.["env"].["state"], - beneficiary, + 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 (| - evm.["env"].["state"], - originator, - ethereum_types.numeric.U256 (| - (* 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* evm.["accounts_to_delete"].["add"] (| - originator - |) in + |) ]] 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 : M unit := +Definition delegatecall (evm : Evm) : M unit := (* Message-call into an account. @@ -419,67 +559,89 @@ Definition delegatecall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - access_gas_cost - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - evm.["message"].["value"], - evm.["message"].["caller"], - evm.["message"].["current_target"], - code_address, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition staticcall (evm : Evm) : M unit := (* Message-call into an account. @@ -488,69 +650,91 @@ Definition staticcall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - access_gas_cost - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - ethereum_types.numeric.U256 (| - (* TODO expression *) + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 |), - evm.["message"].["current_target"], - to, - to, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +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 @@ -559,27 +743,37 @@ Definition revert : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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, - extend_memory.["cost"] - |) in - (* TODO statement *) - let* output := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in + 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.v b/coq/ethereum/london/vm/interpreter.v index 4774a023e4..763d506e64 100644 --- a/coq/ethereum/london/vm/interpreter.v +++ b/coq/ethereum/london/vm/interpreter.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Interpreter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +18,18 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.trace. -Require london.blocks. -Require london.fork_types. -Require london.state. -Require london.vm. -Require london.vm.gas. -Require london.vm.precompiled_contracts.mapping. -Require london.vm.exceptions. -Require london.vm.instructions. -Require london.vm.runtime. - -Definition process_message_call : M unit := +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`. @@ -47,19 +49,21 @@ Definition process_message_call : M unit := *) (* TODO statement *) (* TODO statement *) - let* tx_end := ethereum.trace.TransactionEnd (| - (* TODO expression *), - evm.["output"], - evm.["error"] - |) in - do* ethereum.trace.evm_trace (| - evm, - tx_end - |) in + 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 : M unit := +Definition process_create_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -75,30 +79,32 @@ Definition process_create_message : M unit := evm: :py:class:`~ethereum.london.vm.Evm` Items containing execution specific objects. *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.destroy_storage (| - env.["state"], - message.["current_target"] - |) in - do* state.mark_account_created (| - env.["state"], - message.["current_target"] - |) in - do* state.increment_nonce (| - env.["state"], - message.["current_target"] - |) in - let* evm := process_message (| - message, - env - |) in + 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 : M unit := +Definition process_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -115,23 +121,25 @@ Definition process_message : M unit := Items containing execution specific objects *) (* TODO statement *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.touch_account (| - env.["state"], - message.["current_target"] - |) in + 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 *) - let* evm := execute_code (| - message, - env - |) in + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition execute_code : M unit := +Definition execute_code (message : Message) (env : Environment) : M Evm := (* Executes bytecode present in the `message`. @@ -147,13 +155,19 @@ Definition execute_code : M unit := evm: `ethereum.vm.EVM` Items containing execution specific objects *) - let* code := message.["code"] in - let* valid_jump_destinations := runtime.get_valid_jump_destinations (| - code - |) in - let* evm := Evm (| - - |) in + 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.v b/coq/ethereum/london/vm/memory.v index 94b6a44639..88b516318f 100644 --- a/coq/ethereum/london/vm/memory.v +++ b/coq/ethereum/london/vm/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.byte. -Definition memory_write : M unit := +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := (* Writes to memory. @@ -30,9 +31,9 @@ Definition memory_write : M unit := Data to write to memory. *) (* TODO assignment *) + M.pure tt. - -Definition memory_read_bytes : M unit := +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := (* Read bytes from memory. @@ -51,9 +52,9 @@ Definition memory_read_bytes : M unit := Data read from memory. *) (* TODO statement *) + M.pure tt. - -Definition buffer_read : M unit := +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := (* Read bytes from a buffer. Padding with zeros if necessary. @@ -72,4 +73,4 @@ Definition buffer_read : M unit := Data read from memory. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/london/vm/precompiled_contracts/__init__.v b/coq/ethereum/london/vm/precompiled_contracts/__init__.v index be64961fbf..6e2810bd75 100644 --- a/coq/ethereum/london/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/london/vm/precompiled_contracts/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,4 +14,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require london.utils.hexadecimal. +Require ethereum.london.utils.hexadecimal. diff --git a/coq/ethereum/london/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/london/vm/precompiled_contracts/alt_bn128.v index 611de09a3e..f699b9321a 100644 --- a/coq/ethereum/london/vm/precompiled_contracts/alt_bn128.v +++ b/coq/ethereum/london/vm/precompiled_contracts/alt_bn128.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,12 +15,12 @@ Implementation of the ALT_BN128 precompiled contracts. Require ethereum_types.numeric. Require ethereum.crypto.alt_bn128. -Require london.vm. -Require london.vm.gas. -Require london.vm.memory. -Require london.vm.exceptions. +Require ethereum.london.vm. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.memory. +Require ethereum.london.vm.exceptions. -Definition alt_bn128_add : M unit := +Definition alt_bn128_add (evm : Evm) : M unit := (* The ALT_BN128 addition precompiled contract. @@ -28,76 +29,96 @@ Definition alt_bn128_add : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* x1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x1_bytes - |) - |) in - let* y1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y1_bytes - |) - |) in + 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 *) - let* p := (* TODO expression *) in + do* M.assign "p" [[ + (* TODO expression *) in + ]] in (* TODO assignment *) + M.pure tt. - -Definition alt_bn128_mul : M unit := +Definition alt_bn128_mul (evm : Evm) : M unit := (* The ALT_BN128 multiplication precompiled contract. @@ -106,63 +127,77 @@ Definition alt_bn128_mul : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* n := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) (* TODO statement *) - let* p := p0.["mul_by"] (| - n - |) in + 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 : M unit := +Definition alt_bn128_pairing_check (evm : Evm) : M unit := (* The ALT_BN128 pairing check precompiled contract. @@ -171,17 +206,21 @@ Definition alt_bn128_pairing_check : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 (| + ethereum_types.numeric.Uint ~(| (* TODO expression *) |) - |) in + |) ]] in (* TODO statement *) - let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/london/vm/precompiled_contracts/blake2f.v index ac32ffbf50..bde9d97f03 100644 --- a/coq/ethereum/london/vm/precompiled_contracts/blake2f.v +++ b/coq/ethereum/london/vm/precompiled_contracts/blake2f.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,11 @@ Implementation of the `Blake2` precompiled contract. *) Require ethereum.crypto.blake2. -Require london.vm. -Require london.vm.gas. -Require london.vm.exceptions. +Require ethereum.london.vm. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.exceptions. -Definition blake2f : M unit := +Definition blake2f (evm : Evm) : M unit := (* Writes the Blake2 hash to output. @@ -26,16 +27,20 @@ Definition blake2f : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in (* TODO statement *) - let* blake2b := ethereum.crypto.blake2.Blake2b (| + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| - |) in + |) in + ]] in (* TODO assignment *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, (* TODO expression *) - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/london/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/london/vm/precompiled_contracts/ecrecover.v index 319f0c80a6..1e7530ad14 100644 --- a/coq/ethereum/london/vm/precompiled_contracts/ecrecover.v +++ b/coq/ethereum/london/vm/precompiled_contracts/ecrecover.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,11 +17,11 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require london.vm. -Require london.vm.gas. -Require london.vm.memory. +Require ethereum.london.vm. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.memory. -Definition ecrecover : M unit := +Definition ecrecover (evm : Evm) : M unit := (* Decrypts the address using elliptic curve DSA recovery mechanism and writes the address to output. @@ -30,64 +31,80 @@ Definition ecrecover : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* message_hash_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* message_hash := ethereum.crypto.hash.Hash32 (| - message_hash_bytes - |) in - let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + ethereum_types.numeric.U256 ~(| + 32 |) - |) - |) in - let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 + ]] 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 *) - let* address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/london/vm/precompiled_contracts/identity.v index 553b8203e8..ea3b810ae4 100644 --- a/coq/ethereum/london/vm/precompiled_contracts/identity.v +++ b/coq/ethereum/london/vm/precompiled_contracts/identity.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,10 @@ Implementation of the `IDENTITY` precompiled contract. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require london.vm. -Require london.vm.gas. +Require ethereum.london.vm. +Require ethereum.london.vm.gas. -Definition identity : M unit := +Definition identity (evm : Evm) : M unit := (* Writes the message data to output. @@ -26,11 +27,15 @@ Definition identity : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/london/vm/precompiled_contracts/mapping.v b/coq/ethereum/london/vm/precompiled_contracts/mapping.v index 19fbe5b55f..3ea5f796d0 100644 --- a/coq/ethereum/london/vm/precompiled_contracts/mapping.v +++ b/coq/ethereum/london/vm/precompiled_contracts/mapping.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Mapping of precompiled contracts their implementations. *) Require typing. -Require london.fork_types. -Require london.vm.precompiled_contracts.alt_bn128. -Require london.vm.precompiled_contracts.blake2f. -Require london.vm.precompiled_contracts.ecrecover. -Require london.vm.precompiled_contracts.identity. -Require london.vm.precompiled_contracts.modexp. -Require london.vm.precompiled_contracts.ripemd160. -Require london.vm.precompiled_contracts.sha256. +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.v b/coq/ethereum/london/vm/precompiled_contracts/modexp.v index 2773a521e4..ec7667d338 100644 --- a/coq/ethereum/london/vm/precompiled_contracts/modexp.v +++ b/coq/ethereum/london/vm/precompiled_contracts/modexp.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,100 +15,120 @@ Implementation of the `MODEXP` precompiled contract. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require london.vm. -Require london.vm.gas. -Require london.vm.memory. +Require ethereum.london.vm. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.memory. -Definition modexp : M unit := +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. *) - let* data := evm.["message"].["data"] in - let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) - |) in - let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 - let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* exp_start := (* TODO expression *) in - let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - min (| - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 |), - exp_length + ethereum_types.numeric.U256 ~(| + 32 + |) |) - |) - |) in - do* vm.gas.charge_gas (| + |) 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, - gas_cost (| - base_length, - modulus_length, - exp_length, - exp_head + 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 + |) ]] in (* TODO statement *) - let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - base_length - |) - |) in - let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - exp_length - |) - |) in - let* modulus_start := (* TODO expression *) in - let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - modulus_start, - modulus_length - |) - |) in + 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 : M unit := +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := (* Estimate the complexity of performing a modular exponentiation. @@ -126,19 +147,23 @@ Definition complexity : M unit := complexity : `Uint` Complexity of performing the operation. *) - let* max_length := max (| - ethereum_types.numeric.Uint (| - base_length - |), - ethereum_types.numeric.Uint (| - modulus_length - |) - |) in - let* words := (* TODO expression *) in + 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 : M unit := +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := (* Calculate the number of iterations required to perform a modular exponentiation. @@ -161,9 +186,9 @@ Definition iterations : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition gas_cost : M unit := +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. @@ -189,15 +214,23 @@ Definition gas_cost : M unit := gas_cost : `Uint` Gas required for performing the operation. *) - let* multiplication_complexity := complexity (| - base_length, - modulus_length - |) in - let* iteration_count := iterations (| - exponent_length, - exponent_head - |) in - let* cost := (* TODO expression *) in - (* TODO statement *) + 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.v b/coq/ethereum/london/vm/precompiled_contracts/ripemd160.v index bc5e73dd3c..fe2c66bbe6 100644 --- a/coq/ethereum/london/vm/precompiled_contracts/ripemd160.v +++ b/coq/ethereum/london/vm/precompiled_contracts/ripemd160.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `RIPEMD160` precompiled contract. *) -Definition ripemd160 : M unit := +Definition ripemd160 (evm : Evm) : M unit := (* Writes the ripemd160 hash to output. @@ -22,21 +23,29 @@ Definition ripemd160 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 - let* hash_bytes := hashlib.["new"] (| - (* TODO expression *), - data - |).["digest"] (| - - |) in - let* padded_hash := left_pad_zero_bytes (| - hash_bytes, - (* TODO expression *) - |) in + |) ]] 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.v b/coq/ethereum/london/vm/precompiled_contracts/sha256.v index da6972d411..3ba3ffe7aa 100644 --- a/coq/ethereum/london/vm/precompiled_contracts/sha256.v +++ b/coq/ethereum/london/vm/precompiled_contracts/sha256.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `SHA256` precompiled contract. *) -Definition sha256 : M unit := +Definition sha256 (evm : Evm) : M unit := (* Writes the sha256 hash to output. @@ -22,11 +23,15 @@ Definition sha256 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/london/vm/runtime.v b/coq/ethereum/london/vm/runtime.v index 5045bead7a..c62fb345c2 100644 --- a/coq/ethereum/london/vm/runtime.v +++ b/coq/ethereum/london/vm/runtime.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Runtime Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Runtime related operations used while executing EVM code. Require typing. Require ethereum_types.numeric. -Require london.vm.instructions. +Require ethereum.london.vm.instructions. -Definition get_valid_jump_destinations : M unit := +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := (* Analyze the evm code to obtain the set of valid jump destinations. @@ -38,12 +39,16 @@ Definition get_valid_jump_destinations : M unit := valid_jump_destinations: `Set[Uint]` The set of valid jump destinations in the code. *) - let* valid_jump_destinations := set (| - - |) in - let* pc := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/london/vm/stack.v index 497e3e882e..d0e6b6e1dd 100644 --- a/coq/ethereum/london/vm/stack.v +++ b/coq/ethereum/london/vm/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Implementation of the stack operators for the EVM. Require typing. Require ethereum_types.numeric. -Require london.vm.exceptions. +Require ethereum.london.vm.exceptions. -Definition pop : M unit := +Definition pop (stack : (* TODO type *)) : M U256 := (* Pops the top item off of `stack`. @@ -33,9 +34,9 @@ Definition pop : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition push : M unit := +Definition push (stack : (* TODO type *)) (value : U256) : M unit := (* Pushes `value` onto `stack`. @@ -50,4 +51,4 @@ Definition push : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/muir_glacier/__init__.v b/coq/ethereum/muir_glacier/__init__.v index e38f98952a..80494e48e6 100644 --- a/coq/ethereum/muir_glacier/__init__.v +++ b/coq/ethereum/muir_glacier/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* The Muir Glacier fork delays the difficulty bomb. There are no other changes in this fork. diff --git a/coq/ethereum/muir_glacier/blocks.v b/coq/ethereum/muir_glacier/blocks.v index 9109c50849..97352b0946 100644 --- a/coq/ethereum/muir_glacier/blocks.v +++ b/coq/ethereum/muir_glacier/blocks.v @@ -1,3 +1,4 @@ +(* 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 @@ -14,6 +15,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. -Require muir_glacier.fork_types. -Require muir_glacier.transactions. +Require ethereum.crypto.hash. +Require ethereum.muir_glacier.fork_types. +Require ethereum.muir_glacier.transactions. diff --git a/coq/ethereum/muir_glacier/bloom.v b/coq/ethereum/muir_glacier/bloom.v index b1702993bc..04e052342c 100644 --- a/coq/ethereum/muir_glacier/bloom.v +++ b/coq/ethereum/muir_glacier/bloom.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Logs Bloom ^^^^^^^^^^^^^^^^^^^ @@ -19,10 +20,10 @@ eliminating blocks and receipts from their search. Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require muir_glacier.blocks. -Require muir_glacier.fork_types. +Require ethereum.muir_glacier.blocks. +Require ethereum.muir_glacier.fork_types. -Definition add_to_bloom : M unit := +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := (* Add a bloom entry to the bloom filter (`bloom`). @@ -37,13 +38,15 @@ Definition add_to_bloom : M unit := bloom_entry : An entry which is to be added to bloom filter. *) - let* hash := ethereum.crypto.hash.keccak256 (| - bloom_entry - |) in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition logs_bloom : M unit := +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := (* Obtain the logs bloom from a list of log entries. @@ -63,4 +66,4 @@ Definition logs_bloom : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/muir_glacier/fork.v b/coq/ethereum/muir_glacier/fork.v index 0a62c46841..e7d31608a0 100644 --- a/coq/ethereum/muir_glacier/fork.v +++ b/coq/ethereum/muir_glacier/fork.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^ @@ -20,16 +21,18 @@ Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.ethash. Require ethereum.exceptions. -Require muir_glacier.blocks. -Require muir_glacier.bloom. -Require muir_glacier.fork_types. -Require muir_glacier.state. -Require muir_glacier.transactions. -Require muir_glacier.trie. -Require muir_glacier.utils.message. -Require muir_glacier.vm.interpreter. - -Definition apply_fork : M unit := +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. @@ -49,9 +52,9 @@ Definition apply_fork : M unit := Upgraded block chain object for this hard fork. *) (* TODO statement *) + M.pure tt. - -Definition get_last_256_block_hashes : M unit := +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. @@ -71,22 +74,28 @@ Definition get_last_256_block_hashes : M unit := recent_block_hashes : `List[Hash32]` Hashes of the recent 256 blocks in order of increasing block number. *) - let* recent_blocks := (* TODO expression *) in - (* TODO statement *) - let* recent_block_hashes := (* TODO expression *) in - (* TODO statement *) - let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *).["header"] - |) - |) in - do* recent_block_hashes.["append"] (| - most_recent_block_hash - |) in - (* TODO statement *) - - -Definition state_transition : M unit := + 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. @@ -108,42 +117,46 @@ Definition state_transition : M unit := block : Block to apply to `chain`. *) - let* parent_header := (* TODO expression *).["header"] in - do* validate_header (| - block.["header"], - parent_header - |) in - do* validate_ommers (| - block.["ommers"], - block.["header"], + 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 - let* apply_body_output := apply_body (| - chain.["state"], - get_last_256_block_hashes (| - chain - |), - block.["header"].["coinbase"], - block.["header"].["number"], - block.["header"].["gas_limit"], - block.["header"].["timestamp"], - block.["header"].["difficulty"], - block.["transactions"], - block.["ommers"], - chain.["chain_id"] - |) in + |) ]] 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* chain.["blocks"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| block - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition validate_header : M unit := +Definition validate_header (header : Header) (parent_header : Header) : M unit := (* Verifies a block header. @@ -161,31 +174,37 @@ Definition validate_header : M unit := parent_header : Parent Header of the header to check for correctness *) - let* parent_has_ommers := (* TODO expression *) in + do* M.assign "parent_has_ommers" [[ + (* TODO expression *) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* block_difficulty := calculate_block_difficulty (| - header.["number"], - header.["timestamp"], - parent_header.["timestamp"], - parent_header.["difficulty"], - parent_has_ommers - |) in + 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 *) - let* block_parent_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - parent_header - |) - |) in + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in (* TODO statement *) - do* validate_proof_of_work (| + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| header - |) in - + |) ]] in + M.pure tt. -Definition generate_header_hash_for_pow : M unit := +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. @@ -208,11 +227,13 @@ Definition generate_header_hash_for_pow : M unit := hash : `Hash32` The PoW valid rlp hash of the passed in header. *) - let* header_data_without_pow_artefacts := (* TODO expression *) in + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition validate_proof_of_work : M unit := +Definition validate_proof_of_work (header : Header) : M unit := (* Validates the Proof of Work constraints. @@ -227,19 +248,25 @@ Definition validate_proof_of_work : M unit := header : Header of interest. *) - let* header_hash := generate_header_hash_for_pow (| - header - |) in - let* cache := ethereum.ethash.generate_cache (| - header.["number"] - |) in + 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 *) - let* limit := (* TODO expression *) in + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition check_transaction : M unit := +Definition check_transaction (tx : Transaction) (gas_available : Uint) (chain_id : U64) : M Address := (* Check if the transaction is includable in the block. @@ -263,14 +290,16 @@ Definition check_transaction : M unit := If the transaction is not includable. *) (* TODO statement *) - let* sender_address := recover_sender (| - chain_id, - tx - |) in + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition make_receipt : M unit := +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. @@ -291,13 +320,15 @@ Definition make_receipt : M unit := receipt : The receipt for the transaction. *) - let* receipt := blocks.Receipt (| + do* M.assign "receipt" [[ + blocks.Receipt ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition apply_body : M unit := +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. @@ -338,25 +369,31 @@ Definition apply_body : M unit := apply_body_output : `ApplyBodyOutput` Output of applying the block body to the state. *) - let* gas_available := block_gas_limit in + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - do* pay_rewards (| + do* [[ M.get_local ~(| "pay_rewards" |) ~(| state, block_number, coinbase, ommers - |) in - let* block_gas_used := (* TODO expression *) in - let* block_logs_bloom := bloom.logs_bloom (| - block_logs - |) in - (* TODO statement *) - - -Definition validate_ommers : M unit := + |) ]] 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. @@ -378,23 +415,31 @@ Definition validate_ommers : M unit := chain : History and current state. *) - let* block_hash := rlp.["rlp_hash"] (| - block_header - |) in + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* ommers_hashes := (* TODO expression *) in + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* recent_canonical_blocks := (* TODO expression *) in - let* recent_canonical_block_hashes := (* TODO expression *) in + 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 : M unit := +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. @@ -420,21 +465,25 @@ Definition pay_rewards : M unit := ommers : List of ommers mentioned in the current block. *) - let* ommer_count := ethereum_types.numeric.U256 (| - len (| - ommers - |) - |) in - let* miner_reward := (* TODO expression *) in - do* state.create_ether (| + 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, - miner_reward - |) in + M.get_local ~(| "miner_reward" |) + |) ]] in (* TODO statement *) + M.pure tt. - -Definition process_transaction : M unit := +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := (* Execute a transaction against the provided environment. @@ -462,64 +511,92 @@ Definition process_transaction : M unit := Logs generated during execution. *) (* TODO statement *) - let* sender := env.["origin"] in - let* sender_account := state.get_account (| - env.["state"], - sender - |) in - let* gas_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* gas := (* TODO expression *) in - do* state.increment_nonce (| - env.["state"], - sender - |) in - let* sender_balance_after_gas_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - ethereum_types.numeric.U256 (| - sender_balance_after_gas_fee - |) - |) in - let* message := utils.message.prepare_message (| - sender, - tx.["to"], - tx.["value"], - tx.["data"], - gas, - env - |) in - let* output := vm.interpreter.process_message_call (| - message, - env - |) in - let* gas_used := (* TODO expression *) in - let* gas_refund := min (| - (* TODO expression *), - ethereum_types.numeric.Uint (| - output.["refund_counter"] + 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 - let* gas_refund_amount := (* TODO expression *) in - let* transaction_fee := (* TODO expression *) in - let* total_gas_used := (* TODO expression *) in - let* sender_balance_after_refund := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - sender_balance_after_refund - |) in - let* coinbase_balance_after_mining_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - - -Definition validate_transaction : M unit := + |) ]] 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. @@ -547,9 +624,9 @@ Definition validate_transaction : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition calculate_intrinsic_cost : M unit := +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := (* Calculates the gas that is charged before execution is started. @@ -572,13 +649,15 @@ Definition calculate_intrinsic_cost : M unit := verified : `ethereum.base_types.Uint` The intrinsic cost of the transaction. *) - let* data_cost := (* TODO expression *) in + do* M.assign "data_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition recover_sender : M unit := +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := (* Extracts the sender address from a transaction. @@ -605,9 +684,9 @@ Definition recover_sender : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_pre155 : M unit := +Definition signing_hash_pre155 (tx : Transaction) : M Hash32 := (* Compute the hash of a transaction used in a legacy (pre EIP 155) signature. @@ -622,9 +701,9 @@ Definition signing_hash_pre155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_155 : M unit := +Definition signing_hash_155 (tx : Transaction) (chain_id : U64) : M Hash32 := (* Compute the hash of a transaction used in a EIP 155 signature. @@ -641,9 +720,9 @@ Definition signing_hash_155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition compute_header_hash : M unit := +Definition compute_header_hash (header : Header) : M Hash32 := (* Computes the hash of a block header. @@ -676,9 +755,9 @@ Definition compute_header_hash : M unit := Hash of the header. *) (* TODO statement *) + M.pure tt. - -Definition check_gas_limit : M unit := +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := (* Validates the gas limit for a block. @@ -706,14 +785,16 @@ Definition check_gas_limit : M unit := check : `bool` True if gas limit constraints are satisfied, False otherwise. *) - let* max_adjustment_delta := (* TODO expression *) in + 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 : M unit := +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. @@ -752,9 +833,15 @@ Definition calculate_block_difficulty : M unit := difficulty : `ethereum.base_types.Uint` Computed difficulty for a block. *) - let* offset := (* TODO expression *) in - let* difficulty := (* TODO expression *) in - let* num_bomb_periods := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - + 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.v b/coq/ethereum/muir_glacier/fork_types.v index 14de99d5e5..d84cffdf45 100644 --- a/coq/ethereum/muir_glacier/fork_types.v +++ b/coq/ethereum/muir_glacier/fork_types.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Types ^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. +Require ethereum.__init__. +Require ethereum.crypto.hash. -Definition encode_account : M unit := +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := (* Encode `Account` dataclass. @@ -26,4 +28,4 @@ Definition encode_account : M unit := encoded without providing a storage root. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/muir_glacier/state.v b/coq/ethereum/muir_glacier/state.v index 8bd502c188..a2887a7c0f 100644 --- a/coq/ethereum/muir_glacier/state.v +++ b/coq/ethereum/muir_glacier/state.v @@ -1,3 +1,4 @@ +(* Generated *) (* State ^^^^^ @@ -22,10 +23,10 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require muir_glacier.fork_types. -Require muir_glacier.trie. +Require ethereum.muir_glacier.fork_types. +Require ethereum.muir_glacier.trie. -Definition close_state : M unit := +Definition close_state (state : State) : M unit := (* Free resources held by the state. Used by optimized implementations to release file descriptors. @@ -34,9 +35,9 @@ Definition close_state : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition begin_transaction : M unit := +Definition begin_transaction (state : State) : M unit := (* Start a state transaction. @@ -48,12 +49,12 @@ Definition begin_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition commit_transaction : M unit := +Definition commit_transaction (state : State) : M unit := (* Commit a state transaction. @@ -62,13 +63,13 @@ Definition commit_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["pop"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition rollback_transaction : M unit := +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. @@ -80,9 +81,9 @@ Definition rollback_transaction : M unit := *) (* TODO assignment *) (* TODO statement *) + M.pure tt. - -Definition get_account : M unit := +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. @@ -102,14 +103,16 @@ Definition get_account : M unit := account : `Account` Account at address. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition get_account_optional : M unit := +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. @@ -126,14 +129,16 @@ Definition get_account_optional : M unit := account : `Account` Account at address. *) - let* account := trie.trie_get (| - state.["_main_trie"], - address - |) in + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition set_account : M unit := +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()`). @@ -147,14 +152,14 @@ Definition set_account : M unit := account : `Account` Account to set at address. *) - do* trie.trie_set (| - state.["_main_trie"], + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), address, account - |) in + |) ]] in + M.pure tt. - -Definition destroy_account : M unit := +Definition destroy_account (state : State) (address : Address) : M unit := (* Completely remove the account at `address` and all of its storage. @@ -169,18 +174,18 @@ Definition destroy_account : M unit := address : `Address` Address of account to destroy. *) - do* destroy_storage (| + do* [[ M.get_local ~(| "destroy_storage" |) ~(| state, address - |) in - do* set_account (| + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - (* TODO expression *) - |) in + tt + |) ]] in + M.pure tt. - -Definition destroy_storage : M unit := +Definition destroy_storage (state : State) (address : Address) : M unit := (* Completely remove the storage at `address`. @@ -192,9 +197,9 @@ Definition destroy_storage : M unit := Address of account whose storage is to be deleted. *) (* TODO statement *) + M.pure tt. - -Definition mark_account_created : M unit := +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 @@ -211,12 +216,12 @@ Definition mark_account_created : M unit := address : `Address` Address of the account that has been created. *) - do* state.["created_accounts"].["add"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| address - |) in - + |) ]] in + M.pure tt. -Definition get_storage : M unit := +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. @@ -235,19 +240,23 @@ Definition get_storage : M unit := value : `U256` Value at the key. *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition set_storage : M unit := +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. @@ -264,19 +273,21 @@ Definition set_storage : M unit := Value to set at the key. *) (* TODO statement *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - do* trie.trie_set (| - trie, + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), key, value - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition storage_root : M unit := +Definition storage_root (state : State) (address : Address) : M Root := (* Calculate the storage root of an account. @@ -294,9 +305,9 @@ Definition storage_root : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition state_root : M unit := +Definition state_root (state : State) : M Root := (* Calculate the state root. @@ -313,9 +324,9 @@ Definition state_root : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition account_exists : M unit := +Definition account_exists (state : State) (address : Address) : M bool := (* Checks if an account exists in the state trie @@ -332,9 +343,9 @@ Definition account_exists : M unit := True if account exists in the state trie, False otherwise *) (* TODO statement *) + M.pure tt. - -Definition account_has_code_or_nonce : M unit := +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := (* Checks if an account has non zero nonce or non empty code @@ -351,14 +362,16 @@ Definition account_has_code_or_nonce : M unit := True if if an account has non zero nonce or non empty code, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_empty : M unit := +Definition is_account_empty (state : State) (address : Address) : M bool := (* Checks if an account has zero nonce, empty code and zero balance. @@ -375,14 +388,16 @@ Definition is_account_empty : M unit := True if if an account has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition account_exists_and_is_empty : M unit := +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. @@ -400,14 +415,16 @@ Definition account_exists_and_is_empty : M unit := True if an account exists and has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_alive : M unit := +Definition is_account_alive (state : State) (address : Address) : M bool := (* Check whether is an account is both in the state and non empty. @@ -423,49 +440,51 @@ Definition is_account_alive : M unit := is_alive : `bool` True if the account is alive. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition modify_state : M unit := +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := (* Modify an `Account` in the `State`. *) - do* set_account (| + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - ethereum_types.frozen.modify (| - get_account (| + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| state, address |), f |) - |) in - + |) ]] in + M.pure tt. -Definition move_ether : M unit := +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := (* Move funds between accounts. *) (* TODO statement *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, sender_address, - reduce_sender_balance - |) in - do* modify_state (| + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| state, recipient_address, - increase_recipient_balance - |) in - + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. -Definition set_account_balance : M unit := +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := (* Sets the balance of an account. @@ -481,14 +500,14 @@ Definition set_account_balance : M unit := The amount that needs to set in balance. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - set_balance - |) in + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. - -Definition touch_account : M unit := +Definition touch_account (state : State) (address : Address) : M unit := (* Initializes an account to state. @@ -501,9 +520,9 @@ Definition touch_account : M unit := The address of the account that need to initialised. *) (* TODO statement *) + M.pure tt. - -Definition increment_nonce : M unit := +Definition increment_nonce (state : State) (address : Address) : M unit := (* Increments the nonce of an account. @@ -516,14 +535,14 @@ Definition increment_nonce : M unit := Address of the account whose nonce needs to be incremented. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_nonce - |) in + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. - -Definition set_code : M unit := +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := (* Sets Account code. @@ -539,14 +558,14 @@ Definition set_code : M unit := The bytecode that needs to be set. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - write_code - |) in - + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. -Definition create_ether : M unit := +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := (* Add newly created ether to an account. @@ -560,14 +579,14 @@ Definition create_ether : M unit := The amount of ether to be added to the account of interest. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_balance - |) in - + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. -Definition get_storage_original : M unit := +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 @@ -584,10 +603,12 @@ Definition get_storage_original : M unit := *) (* TODO statement *) (* TODO assignment *) - let* original_account_trie := original_trie.["get"] (| - address - |) in + 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.v b/coq/ethereum/muir_glacier/transactions.v index 27338180fa..9ea3014845 100644 --- a/coq/ethereum/muir_glacier/transactions.v +++ b/coq/ethereum/muir_glacier/transactions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, @@ -9,4 +10,4 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require muir_glacier.fork_types. +Require ethereum.muir_glacier.fork_types. diff --git a/coq/ethereum/muir_glacier/trie.v b/coq/ethereum/muir_glacier/trie.v index 548de91e1c..6b8953f256 100644 --- a/coq/ethereum/muir_glacier/trie.v +++ b/coq/ethereum/muir_glacier/trie.v @@ -1,3 +1,4 @@ +(* Generated *) (* State Trie ^^^^^^^^^^ @@ -14,7 +15,7 @@ The state trie is the structure responsible for storing *) -Definition encode_internal_node : M unit := +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 @@ -35,22 +36,24 @@ Definition encode_internal_node : M unit := *) (* TODO statement *) (* TODO statement *) - let* encoded := rlp.["encode"] (| - unencoded - |) in + 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 : M unit := +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 : M unit := +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. @@ -66,9 +69,9 @@ Definition copy_trie : M unit := A copy of the trie. *) (* TODO statement *) + M.pure tt. - -Definition trie_set : M unit := +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := (* Stores an item in a Merkle Trie. @@ -85,9 +88,9 @@ Definition trie_set : M unit := Node to insert at `key`. *) (* TODO statement *) + M.pure tt. - -Definition trie_get : M unit := +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := (* Gets an item from the Merkle Trie. @@ -106,17 +109,17 @@ Definition trie_get : M unit := Node at `key` in the trie. *) (* TODO statement *) + M.pure tt. - -Definition common_prefix_length : M unit := +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 : M unit := +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := (* Compresses nibble-list into a standard byte array with a flag. @@ -150,14 +153,16 @@ Definition nibble_list_to_compact : M unit := compressed : `bytearray` Compact byte array. *) - let* compact := bytearray (| + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition bytes_to_nibble_list : M unit := +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := (* Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). @@ -171,14 +176,16 @@ Definition bytes_to_nibble_list : M unit := nibble_list : `Bytes` The `Bytes` in nibble-list format. *) - let* nibble_list := bytearray (| - (* TODO expression *) - |) in + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _prepare_trie : M unit := +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. @@ -199,9 +206,9 @@ Definition _prepare_trie : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition root : M unit := +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := (* Computes the root of a modified merkle patricia trie (MPT). @@ -219,22 +226,26 @@ Definition root : M unit := root : `.fork_types.Root` MPT root of the underlying key-value pairs. *) - let* obj := _prepare_trie (| - trie, - get_storage_root - |) in - let* root_node := encode_internal_node (| - patricialize (| - obj, - Uint (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) + M.pure tt. - -Definition patricialize : M unit := +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := (* Structural composition function. @@ -254,21 +265,29 @@ Definition patricialize : M unit := Root node of `obj`. *) (* TODO statement *) - let* arbitrary_key := next (| - iter (| - obj - |) - |) in + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in (* TODO statement *) - let* substring := (* TODO expression *) in - let* prefix_length := len (| - substring - |) in + 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 *) - let* value := (* TODO expression *) in + do* M.assign "value" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/muir_glacier/utils/__init__.v b/coq/ethereum/muir_glacier/utils/__init__.v index beff4482b1..7f30fe939b 100644 --- a/coq/ethereum/muir_glacier/utils/__init__.v +++ b/coq/ethereum/muir_glacier/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions unique to this particular fork. *) diff --git a/coq/ethereum/muir_glacier/utils/address.v b/coq/ethereum/muir_glacier/utils/address.v index 18b2738fb9..160a725a3d 100644 --- a/coq/ethereum/muir_glacier/utils/address.v +++ b/coq/ethereum/muir_glacier/utils/address.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,9 +19,10 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require muir_glacier.fork_types. +Require ethereum.__init__. +Require ethereum.muir_glacier.fork_types. -Definition to_address : M unit := +Definition to_address (data : (* TODO type *)) : M Address := (* Convert a Uint or U256 value to a valid address (20 bytes). @@ -35,9 +37,9 @@ Definition to_address : M unit := The obtained address. *) (* TODO statement *) + M.pure tt. - -Definition compute_contract_address : M unit := +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := (* Computes address of the new account that needs to be created. @@ -54,20 +56,26 @@ Definition compute_contract_address : M unit := address: `Address` The computed address of the new account. *) - let* computed_address := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *) - |) - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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 : M unit := +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. @@ -86,14 +94,22 @@ Definition compute_create2_contract_address : M unit := address: `ethereum.muir_glacier.fork_types.Address` The computed address of the new account. *) - let* preimage := (* TODO expression *) in - let* computed_address := ethereum.crypto.hash.keccak256 (| - preimage - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/muir_glacier/utils/hexadecimal.v index 01dca945a4..4a86da9538 100644 --- a/coq/ethereum/muir_glacier/utils/hexadecimal.v +++ b/coq/ethereum/muir_glacier/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Muir Glacier types. *) Require ethereum.utils.hexadecimal. -Require muir_glacier.fork_types. +Require ethereum.muir_glacier.fork_types. -Definition hex_to_root : M unit := +Definition hex_to_root (hex_string : str) : M Root := (* Convert hex string to trie root. @@ -31,9 +32,9 @@ Definition hex_to_root : M unit := Trie root obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bloom : M unit := +Definition hex_to_bloom (hex_string : str) : M Bloom := (* Convert hex string to bloom. @@ -48,9 +49,9 @@ Definition hex_to_bloom : M unit := Bloom obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_address : M unit := +Definition hex_to_address (hex_string : str) : M Address := (* Convert hex string to Address (20 bytes). @@ -65,4 +66,4 @@ Definition hex_to_address : M unit := The address obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/muir_glacier/utils/message.v b/coq/ethereum/muir_glacier/utils/message.v index d32294a5cf..87df398f73 100644 --- a/coq/ethereum/muir_glacier/utils/message.v +++ b/coq/ethereum/muir_glacier/utils/message.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For The Message Data-structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,12 +17,12 @@ specification. Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require muir_glacier.fork_types. -Require muir_glacier.state. -Require muir_glacier.vm. -Require muir_glacier.utils.address. +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 : M unit := +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. @@ -56,4 +57,4 @@ Definition prepare_message : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/__init__.v b/coq/ethereum/muir_glacier/vm/__init__.v index 6adf91df71..16c9085cfa 100644 --- a/coq/ethereum/muir_glacier/vm/__init__.v +++ b/coq/ethereum/muir_glacier/vm/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,12 +19,12 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require muir_glacier.blocks. -Require muir_glacier.fork_types. -Require muir_glacier.state. -Require muir_glacier.vm.precompiled_contracts. +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 : M unit := +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of a successful `child_evm` into the parent `evm`. @@ -34,19 +35,25 @@ Definition incorporate_child_on_success : M unit := 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 *) - (* TODO statement *) - (* TODO statement *) - do* evm.["accounts_to_delete"].["update"] (| - child_evm.["accounts_to_delete"] - |) in - do* evm.["touched_accounts"].["update"] (| - child_evm.["touched_accounts"] - |) in - (* TODO statement *) + M.pure tt. - -Definition incorporate_child_on_error : M unit := +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. @@ -59,5 +66,7 @@ Definition incorporate_child_on_error : M unit := *) (* TODO statement *) (* 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.v b/coq/ethereum/muir_glacier/vm/exceptions.v index 1784494410..47e26555d5 100644 --- a/coq/ethereum/muir_glacier/vm/exceptions.v +++ b/coq/ethereum/muir_glacier/vm/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Exceptions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/muir_glacier/vm/gas.v b/coq/ethereum/muir_glacier/vm/gas.v index 03239a67ff..59522f596a 100644 --- a/coq/ethereum/muir_glacier/vm/gas.v +++ b/coq/ethereum/muir_glacier/vm/gas.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Gas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,9 +18,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.trace. Require ethereum.utils.numeric. -Require muir_glacier.vm.exceptions. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.exceptions. -Definition charge_gas : M unit := +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := (* Subtracts `amount` from `evm.gas_left`. @@ -31,18 +33,18 @@ Definition charge_gas : M unit := The amount of gas the current operation requires. *) - do* ethereum.trace.evm_trace (| + do* [[ ethereum.trace.evm_trace ~(| evm, - ethereum.trace.GasAndRefund (| - int (| + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| amount |) |) - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_memory_gas_cost : M unit := +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, @@ -58,14 +60,22 @@ Definition calculate_memory_gas_cost : M unit := total_gas_cost : `ethereum.base_types.Uint` The gas cost for storing data in memory. *) - let* size_in_words := (* TODO expression *) in - let* linear_cost := (* TODO expression *) in - let* quadratic_cost := (* TODO expression *) in - let* total_gas_cost := (* TODO expression *) in + 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 : M unit := +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := (* Calculates the gas amount to extend memory @@ -81,22 +91,28 @@ Definition calculate_gas_extend_memory : M unit := ------- extend_memory: `ExtendMemory` *) - let* size_to_extend := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* to_be_paid := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* current_size := ethereum_types.numeric.Uint (| - len (| - memory - |) - |) in + 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 : M unit := +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. @@ -122,18 +138,22 @@ Definition calculate_message_call_gas : M unit := ------- message_call_gas: `MessageCallGas` *) - let* call_stipend := (* TODO expression *) in + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* gas := min (| - gas, - max_message_call_gas (| - (* TODO expression *) - |) - |) in + 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 : M unit := +Definition max_message_call_gas (gas : Uint) : M Uint := (* Calculates the maximum gas that is allowed for making a message call @@ -148,4 +168,4 @@ Definition max_message_call_gas : M unit := The maximum gas allowed for making the message-call. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/instructions/__init__.v b/coq/ethereum/muir_glacier/vm/instructions/__init__.v index b36b1ebfef..cbd7e7e63a 100644 --- a/coq/ethereum/muir_glacier/vm/instructions/__init__.v +++ b/coq/ethereum/muir_glacier/vm/instructions/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* EVM Instruction Encoding (Opcodes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/muir_glacier/vm/instructions/arithmetic.v b/coq/ethereum/muir_glacier/vm/instructions/arithmetic.v index 21be74ba18..f912e92eaf 100644 --- a/coq/ethereum/muir_glacier/vm/instructions/arithmetic.v +++ b/coq/ethereum/muir_glacier/vm/instructions/arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,11 @@ Implementations of the EVM Arithmetic instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require muir_glacier.vm.gas. -Require muir_glacier.vm.stack. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.stack. -Definition add : M unit := +Definition add (evm : Evm) : M unit := (* Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -28,27 +30,37 @@ Definition add : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_add"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sub (evm : Evm) : M unit := (* Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -59,27 +71,37 @@ Definition sub : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_sub"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mul (evm : Evm) : M unit := (* Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -90,27 +112,37 @@ Definition mul : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_mul"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition div (evm : Evm) : M unit := (* Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -121,25 +153,33 @@ Definition div : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |) in - let* divisor := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - quotient - |) 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 : M unit := +Definition sdiv (evm : Evm) : M unit := (* Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -150,31 +190,39 @@ Definition sdiv : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* divisor := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - quotient + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mod : M unit := +Definition mod (evm : Evm) : M unit := (* Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -185,25 +233,33 @@ Definition mod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - remainder - |) in + |) ]] 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 : M unit := +Definition smod (evm : Evm) : M unit := (* Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -214,31 +270,39 @@ Definition smod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* y := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - remainder + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition addmod : M unit := +Definition addmod (evm : Evm) : M unit := (* Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -249,34 +313,44 @@ Definition addmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +Definition mulmod (evm : Evm) : M unit := (* Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -287,34 +361,44 @@ Definition mulmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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 : M unit := +Definition exp (evm : Evm) : M unit := (* Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -325,39 +409,53 @@ Definition exp : M unit := The current EVM frame. *) - let* base := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent_bits := exponent.["bit_length"] (| - - |) in - let* exponent_bytes := (* TODO expression *) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - pow (| - base, - exponent, - (* 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 - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition signextend : M unit := +Definition signextend (evm : Evm) : M unit := (* Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -368,20 +466,28 @@ Definition signextend : M unit := The current EVM frame. *) - let* byte_num := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/muir_glacier/vm/instructions/bitwise.v index 7d747a72ef..a82117cf12 100644 --- a/coq/ethereum/muir_glacier/vm/instructions/bitwise.v +++ b/coq/ethereum/muir_glacier/vm/instructions/bitwise.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Bitwise Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM bitwise instructions. *) Require ethereum_types.numeric. -Require muir_glacier.vm.gas. -Require muir_glacier.vm.stack. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.stack. -Definition bitwise_and : M unit := +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. @@ -27,24 +29,32 @@ Definition bitwise_and : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_or : M unit := +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. @@ -55,24 +65,32 @@ Definition bitwise_or : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_xor : M unit := +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. @@ -83,24 +101,32 @@ Definition bitwise_xor : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_not : M unit := +Definition bitwise_not (evm : Evm) : M unit := (* Bitwise NOT operation of the top element of the stack. Pushes the result back on the stack. @@ -111,21 +137,27 @@ Definition bitwise_not : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition get_byte : M unit := +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 @@ -137,25 +169,33 @@ Definition get_byte : M unit := The current EVM frame. *) - let* byte_index := stack.pop (| - evm.["stack"] - |) in - let* word := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -164,29 +204,37 @@ Definition bitwise_shl : M unit := evm : The current EVM frame. *) - let* shift := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -195,25 +243,33 @@ Definition bitwise_shr : M unit := evm : The current EVM frame. *) - let* shift := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -222,24 +278,32 @@ Definition bitwise_sar : M unit := evm : The current EVM frame. *) - let* shift := int (| - stack.pop (| - evm.["stack"] - |) - |) in - let* signed_value := stack.pop (| - evm.["stack"] - |).["to_signed"] (| + 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 - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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.v b/coq/ethereum/muir_glacier/vm/instructions/block.v index 4fc228e55d..6814eb2a38 100644 --- a/coq/ethereum/muir_glacier/vm/instructions/block.v +++ b/coq/ethereum/muir_glacier/vm/instructions/block.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Block Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM block instructions. *) Require ethereum_types.numeric. -Require muir_glacier.vm.gas. -Require muir_glacier.vm.stack. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.stack. -Definition block_hash : M unit := +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. @@ -27,27 +29,35 @@ Definition block_hash : M unit := The current EVM frame. *) - let* block_number := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* max_block_number := (* TODO expression *) in + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition coinbase : M unit := +Definition coinbase (evm : Evm) : M unit := (* Push the current block's beneficiary address (address of the block miner) onto the stack. @@ -62,20 +72,24 @@ Definition coinbase : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["coinbase"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition timestamp : M unit := +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. @@ -90,18 +104,22 @@ Definition timestamp : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["env"].["time"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition number (evm : Evm) : M unit := (* Push the current block's number onto the stack. @@ -115,20 +133,24 @@ Definition number : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["number"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition difficulty : M unit := +Definition difficulty (evm : Evm) : M unit := (* Push the current block's difficulty onto the stack. @@ -142,20 +164,24 @@ Definition difficulty : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["difficulty"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_limit : M unit := +Definition gas_limit (evm : Evm) : M unit := (* Push the current block's gas limit onto the stack. @@ -169,20 +195,24 @@ Definition gas_limit : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_limit"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition chain_id : M unit := +Definition chain_id (evm : Evm) : M unit := (* Push the chain id onto the stack. @@ -193,15 +223,19 @@ Definition chain_id : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["chain_id"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/muir_glacier/vm/instructions/comparison.v index fa5d4164ce..7085c25f4b 100644 --- a/coq/ethereum/muir_glacier/vm/instructions/comparison.v +++ b/coq/ethereum/muir_glacier/vm/instructions/comparison.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Comparison Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM Comparison instructions. *) Require ethereum_types.numeric. -Require muir_glacier.vm.gas. -Require muir_glacier.vm.stack. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.stack. -Definition less_than : M unit := +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. @@ -27,27 +29,37 @@ Definition less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_less_than : M unit := + |) ]] 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. @@ -57,31 +69,41 @@ Definition signed_less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition greater_than : M unit := + |) ]] 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. @@ -92,27 +114,37 @@ Definition greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_greater_than : M unit := + |) ]] 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. @@ -122,31 +154,41 @@ Definition signed_greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition equal : M unit := + |) ]] 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. @@ -157,27 +199,37 @@ Definition equal : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition is_zero : M unit := + |) ]] 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. @@ -188,19 +240,27 @@ Definition is_zero : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/muir_glacier/vm/instructions/control_flow.v index a8793d599e..2b26336f1f 100644 --- a/coq/ethereum/muir_glacier/vm/instructions/control_flow.v +++ b/coq/ethereum/muir_glacier/vm/instructions/control_flow.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Control Flow Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM control flow instructions. *) Require ethereum_types.numeric. -Require muir_glacier.vm.gas. -Require muir_glacier.vm.exceptions. -Require muir_glacier.vm.stack. +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 : M unit := +Definition stop (evm : Evm) : M unit := (* Stop further execution of EVM code. @@ -29,10 +31,14 @@ Definition stop : M unit := (* TODO statement *) (* TODO statement *) (* TODO assignment *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jump : M unit := +Definition jump (evm : Evm) : M unit := (* Alter the program counter to the location specified by the top of the stack. @@ -43,20 +49,22 @@ Definition jump : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition jumpi : M unit := +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 @@ -68,23 +76,27 @@ Definition jumpi : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* conditional_value := stack.pop (| - evm.["stack"] - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition pc : M unit := +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. @@ -96,20 +108,24 @@ Definition pc : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["pc"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_left : M unit := +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. @@ -121,20 +137,24 @@ Definition gas_left : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["gas_left"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jumpdest : M unit := +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 @@ -147,10 +167,14 @@ Definition jumpdest : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_JUMPDEST - |) in - (* TODO statement *) + |) ]] 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.v b/coq/ethereum/muir_glacier/vm/instructions/environment.v index 7d0903a808..a3eaac0f46 100644 --- a/coq/ethereum/muir_glacier/vm/instructions/environment.v +++ b/coq/ethereum/muir_glacier/vm/instructions/environment.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,15 +16,16 @@ Implementations of the EVM environment related instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require muir_glacier.fork_types. -Require muir_glacier.state. -Require muir_glacier.utils.address. -Require muir_glacier.vm.memory. -Require muir_glacier.vm.exceptions. -Require muir_glacier.vm.gas. -Require muir_glacier.vm.stack. - -Definition address : M unit := +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. @@ -34,20 +36,24 @@ Definition address : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["current_target"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition balance : M unit := +Definition balance (evm : Evm) : M unit := (* Pushes the balance of the given account onto the stack. @@ -57,27 +63,35 @@ Definition balance : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* balance := state.get_account (| - evm.["env"].["state"], - address - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +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. @@ -89,20 +103,24 @@ Definition origin : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["origin"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition caller : M unit := +Definition caller (evm : Evm) : M unit := (* Pushes the address of the caller onto the stack. @@ -113,20 +131,24 @@ Definition caller : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["caller"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition callvalue : M unit := +Definition callvalue (evm : Evm) : M unit := (* Push the value (in wei) sent with the call onto the stack. @@ -137,18 +159,22 @@ Definition callvalue : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["message"].["value"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition calldataload (evm : Evm) : M unit := (* Push a word (32 bytes) of the input data belonging to the current environment onto the stack. @@ -159,30 +185,38 @@ Definition calldataload : M unit := The current EVM frame. *) - let* start_index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - start_index, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] 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* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - value + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 |) - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition calldatasize : M unit := +Definition calldatasize (evm : Evm) : M unit := (* Push the size of input data in current environment onto the stack. @@ -193,22 +227,26 @@ Definition calldatasize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["message"].["data"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition calldatacopy : M unit := +Definition calldatacopy (evm : Evm) : M unit := (* Copy a portion of the input data in current environment to memory. @@ -221,40 +259,60 @@ Definition calldatacopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* data_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - data_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition codesize (evm : Evm) : M unit := (* Push the size of code running in current environment onto the stack. @@ -265,22 +323,26 @@ Definition codesize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["code"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition codecopy : M unit := +Definition codecopy (evm : Evm) : M unit := (* Copy a portion of the code in current environment to memory. @@ -293,40 +355,60 @@ Definition codecopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["code"], - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition gasprice (evm : Evm) : M unit := (* Push the gas price used in current environment onto the stack. @@ -337,20 +419,24 @@ Definition gasprice : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_price"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition extcodesize : M unit := +Definition extcodesize (evm : Evm) : M unit := (* Push the code size of a given account onto the stack. @@ -360,31 +446,39 @@ Definition extcodesize : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* codesize := ethereum_types.numeric.U256 (| - len (| - state.get_account (| - evm.["env"].["state"], - address - |).["code"] + |) ]] 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 - do* stack.push (| - evm.["stack"], - codesize - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition extcodecopy : M unit := +Definition extcodecopy (evm : Evm) : M unit := (* Copy a portion of an account's code to memory. @@ -394,49 +488,73 @@ Definition extcodecopy : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* code := state.get_account (| - evm.["env"].["state"], - address - |).["code"] in - let* value := vm.memory.buffer_read (| - code, - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition returndatasize (evm : Evm) : M unit := (* Pushes the size of the return data buffer onto the stack. @@ -446,22 +564,26 @@ Definition returndatasize : M unit := The current EVM frame. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["return_data"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition returndatacopy : M unit := +Definition returndatacopy (evm : Evm) : M unit := (* Copies data from the return data buffer code to memory @@ -470,37 +592,57 @@ Definition returndatacopy : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* return_data_start_position := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - (* TODO statement *) - let* value := (* TODO expression *) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) 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 : M unit := +Definition extcodehash (evm : Evm) : M unit := (* Returns the keccak256 hash of a contract’s bytecode Parameters @@ -508,28 +650,36 @@ Definition extcodehash : M unit := evm : The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* account := state.get_account (| - evm.["env"].["state"], - address - |) in - (* TODO statement *) - do* stack.push (| - evm.["stack"], - codehash - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition self_balance (evm : Evm) : M unit := (* Pushes the balance of the current address to the stack. @@ -540,17 +690,23 @@ Definition self_balance : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_FAST_STEP - |) in - let* balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/muir_glacier/vm/instructions/keccak.v index ffa8a22592..e6d9aae163 100644 --- a/coq/ethereum/muir_glacier/vm/instructions/keccak.v +++ b/coq/ethereum/muir_glacier/vm/instructions/keccak.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Keccak Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM keccak instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require muir_glacier.vm.gas. -Require muir_glacier.vm.memory. -Require muir_glacier.vm.stack. +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 : M unit := +Definition keccak (evm : Evm) : M unit := (* Pushes to the stack the Keccak-256 hash of a region of memory. @@ -32,36 +34,56 @@ Definition keccak : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* word_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in - let* hash := ethereum.crypto.hash.keccak256 (| - data - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/muir_glacier/vm/instructions/log.v index dca012fe14..92d3d9d180 100644 --- a/coq/ethereum/muir_glacier/vm/instructions/log.v +++ b/coq/ethereum/muir_glacier/vm/instructions/log.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Logging Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,13 +15,14 @@ Implementations of the EVM logging instructions. Require functools. Require ethereum_types.numeric. -Require muir_glacier.blocks. -Require muir_glacier.vm.exceptions. -Require muir_glacier.vm.gas. -Require muir_glacier.vm.memory. -Require muir_glacier.vm.stack. +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 : M unit := +Definition log_n (evm : Evm) (num_topics : U256) : M unit := (* Appends a log entry, having `num_topics` topics, to the evm logs. @@ -35,27 +37,43 @@ Definition log_n : M unit := The number of topics to be included in the log entry. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* topics := (* TODO expression *) in + 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 *) - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in (* TODO statement *) - let* log_entry := blocks.Log (| + do* M.assign "log_entry" [[ + blocks.Log ~(| - |) in + |) in + ]] in (* TODO assignment *) - (* 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/memory.v b/coq/ethereum/muir_glacier/vm/instructions/memory.v index d45d56bf00..da9feaf56a 100644 --- a/coq/ethereum/muir_glacier/vm/instructions/memory.v +++ b/coq/ethereum/muir_glacier/vm/instructions/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM Memory instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require muir_glacier.vm.gas. -Require muir_glacier.vm.memory. -Require muir_glacier.vm.stack. +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 : M unit := +Definition mstore (evm : Evm) : M unit := (* Stores a word to memory. This also expands the memory, if the memory is @@ -30,32 +32,44 @@ Definition mstore : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* memory.memory_write (| - evm.["memory"], - start_position, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mstore8 (evm : Evm) : M unit := (* Stores a byte to memory. This also expands the memory, if the memory is @@ -67,33 +81,47 @@ Definition mstore8 : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ (* TODO expression *) - |) in - do* memory.memory_write (| - evm.["memory"], - start_position, - normalized_bytes_value - |) in - (* TODO statement *) - + ]] 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 : M unit := +Definition mload (evm : Evm) : M unit := (* Load word from memory. @@ -103,35 +131,47 @@ Definition mload : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.memory_read_bytes (| - evm.["memory"], - start_position, - ethereum_types.numeric.U256 (| - (* 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 - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition msize : M unit := +Definition msize (evm : Evm) : M unit := (* Push the size of active memory in bytes onto the stack. @@ -142,17 +182,21 @@ Definition msize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["memory"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/muir_glacier/vm/instructions/stack.v index f135418b24..b2e2b644ff 100644 --- a/coq/ethereum/muir_glacier/vm/instructions/stack.v +++ b/coq/ethereum/muir_glacier/vm/instructions/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM stack related instructions. Require functools. Require ethereum_types.numeric. -Require muir_glacier.vm.exceptions. -Require muir_glacier.vm.gas. -Require 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.memory. -Definition pop : M unit := +Definition pop (evm : Evm) : M unit := (* Remove item from stack. @@ -28,18 +30,22 @@ Definition pop : M unit := The current EVM frame. *) - do* stack.["pop"] (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in + |) ]] in (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition push_n : M unit := +Definition push_n (evm : Evm) (num_bytes : int) : M unit := (* Pushes a N-byte immediate onto the stack. @@ -54,29 +60,33 @@ Definition push_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - evm.["code"], - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - num_bytes + |) ]] 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 - do* stack.["push"] (| - evm.["stack"], - data_to_push - |) in - (* TODO statement *) - - -Definition dup_n : M unit := + |) 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. @@ -91,20 +101,26 @@ Definition dup_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - let* data_to_duplicate := (* TODO expression *) in - do* stack.["push"] (| - evm.["stack"], - data_to_duplicate - |) 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 : M unit := +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. @@ -123,11 +139,15 @@ Definition swap_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - (* 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/storage.v b/coq/ethereum/muir_glacier/vm/instructions/storage.v index 1eb4772eb7..874f302440 100644 --- a/coq/ethereum/muir_glacier/vm/instructions/storage.v +++ b/coq/ethereum/muir_glacier/vm/instructions/storage.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Storage Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,12 +14,13 @@ Implementations of the EVM storage related instructions. *) Require ethereum_types.numeric. -Require muir_glacier.state. -Require muir_glacier.vm.exceptions. -Require muir_glacier.vm.gas. -Require muir_glacier.vm.stack. +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 : M unit := +Definition sload (evm : Evm) : M unit := (* Loads to the stack, the value corresponding to a certain key from the storage of the current account. @@ -29,28 +31,36 @@ Definition sload : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_SLOAD - |) in - let* value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sstore (evm : Evm) : M unit := (* Stores a value at a certain key in the current context's storage. @@ -60,37 +70,49 @@ Definition sstore : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in (* TODO statement *) - let* original_value := state.get_storage_original (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - let* current_value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in + M.get_local ~(| "gas_cost" |) + |) ]] in (* TODO statement *) - do* state.set_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key, - new_value - |) 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.v b/coq/ethereum/muir_glacier/vm/instructions/system.v index e7fcb0f5f5..e7edbce2ce 100644 --- a/coq/ethereum/muir_glacier/vm/instructions/system.v +++ b/coq/ethereum/muir_glacier/vm/instructions/system.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) System Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,54 +16,69 @@ Implementations of the EVM system related instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require muir_glacier.fork_types. -Require muir_glacier.state. -Require muir_glacier.utils.address. -Require muir_glacier.vm.exceptions. -Require muir_glacier.vm.gas. -Require muir_glacier.vm.memory. -Require muir_glacier.vm.stack. - -Definition generic_create : M unit := +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 *) - let* create_message_gas := gas.max_message_call_gas (| - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |) - |) in - (* 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 *) - let* sender_address := evm.["message"].["current_target"] in - let* sender := state.get_account (| - evm.["env"].["state"], - sender_address - |) in - (* TODO statement *) - (* TODO statement *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) in - do* state.increment_nonce (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |) in - let* child_message := Message (| - - |) in - let* child_evm := process_create_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - - -Definition create : M unit := + 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. @@ -71,42 +87,58 @@ Definition create : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_contract_address (| - evm.["message"].["current_target"], - state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["nonce"] - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition create2 (evm : Evm) : M unit := (* Creates a new account with associated code. @@ -118,50 +150,70 @@ Definition create2 : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* salt := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* call_data_words := (* TODO expression *) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_create2_contract_address (| - evm.["message"].["current_target"], - salt, - memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size - |) in - (* TODO statement *) - + 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_ : M unit := +Definition return_ (evm : Evm) : M unit := (* Halts execution returning output data. @@ -170,66 +222,84 @@ Definition return_ : M unit := evm : The current EVM frame. *) - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) + |) ]] 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 : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_input_start_position, - memory_input_size - |) in - let* code := state.get_account (| - evm.["env"].["state"], - code_address - |).["code"] in - let* child_message := Message (| - - |) in - let* child_evm := process_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - let* actual_output_size := min (| - memory_output_size, - ethereum_types.numeric.U256 (| - len (| - child_evm.["output"] + 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 - do* memory.memory_write (| - evm.["memory"], + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), memory_output_start_position, (* TODO expression *) - |) in + |) ]] in + M.pure tt. - -Definition call : M unit := +Definition call (evm : Evm) : M unit := (* Message-call into an account. @@ -238,61 +308,91 @@ Definition call : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* create_gas_cost := (* TODO expression *) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) - (* 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 : M unit := +Definition callcode (evm : Evm) : M unit := (* Message-call into this account with alternative account’s code. @@ -301,60 +401,90 @@ Definition callcode : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* to := evm.["message"].["current_target"] in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) - (* TODO statement *) - + |) ]] 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 : M unit := +Definition selfdestruct (evm : Evm) : M unit := (* Halt execution and register account for later deletion. @@ -363,52 +493,66 @@ Definition selfdestruct : M unit := evm : The current EVM frame. *) - let* beneficiary := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* gas_cost := gas.GAS_SELF_DESTRUCT in - (* TODO statement *) - let* originator := evm.["message"].["current_target"] in - let* refunded_accounts := evm.["accounts_to_delete"] in - let* parent_evm := evm.["message"].["parent_evm"] in - (* TODO statement *) - (* TODO statement *) - do* gas.charge_gas (| + 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, - gas_cost - |) in - (* TODO statement *) - let* beneficiary_balance := state.get_account (| - evm.["env"].["state"], - beneficiary - |).["balance"] in - let* originator_balance := state.get_account (| - evm.["env"].["state"], - originator - |).["balance"] in - do* state.set_account_balance (| - evm.["env"].["state"], - beneficiary, + 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 (| - evm.["env"].["state"], - originator, - ethereum_types.numeric.U256 (| - (* 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* evm.["accounts_to_delete"].["add"] (| - originator - |) in + |) ]] 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 : M unit := +Definition delegatecall (evm : Evm) : M unit := (* Message-call into an account. @@ -417,66 +561,88 @@ Definition delegatecall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - gas.GAS_CALL - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - evm.["message"].["value"], - evm.["message"].["caller"], - evm.["message"].["current_target"], - code_address, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition staticcall (evm : Evm) : M unit := (* Message-call into an account. @@ -485,68 +651,90 @@ Definition staticcall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - gas.GAS_CALL - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - ethereum_types.numeric.U256 (| - (* TODO expression *) + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 |), - evm.["message"].["current_target"], - to, - to, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +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 @@ -555,27 +743,37 @@ Definition revert : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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, - extend_memory.["cost"] - |) in - (* TODO statement *) - let* output := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in + 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.v b/coq/ethereum/muir_glacier/vm/interpreter.v index 10947850c4..8813c774e6 100644 --- a/coq/ethereum/muir_glacier/vm/interpreter.v +++ b/coq/ethereum/muir_glacier/vm/interpreter.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Interpreter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +18,18 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.trace. -Require muir_glacier.blocks. -Require muir_glacier.fork_types. -Require muir_glacier.state. -Require muir_glacier.vm. -Require muir_glacier.vm.gas. -Require muir_glacier.vm.precompiled_contracts.mapping. -Require muir_glacier.vm.exceptions. -Require muir_glacier.vm.instructions. -Require muir_glacier.vm.runtime. - -Definition process_message_call : M unit := +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`. @@ -47,19 +49,21 @@ Definition process_message_call : M unit := *) (* TODO statement *) (* TODO statement *) - let* tx_end := ethereum.trace.TransactionEnd (| - (* TODO expression *), - evm.["output"], - evm.["error"] - |) in - do* ethereum.trace.evm_trace (| - evm, - tx_end - |) in + 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 : M unit := +Definition process_create_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -75,30 +79,32 @@ Definition process_create_message : M unit := evm: :py:class:`~ethereum.muir_glacier.vm.Evm` Items containing execution specific objects. *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.destroy_storage (| - env.["state"], - message.["current_target"] - |) in - do* state.mark_account_created (| - env.["state"], - message.["current_target"] - |) in - do* state.increment_nonce (| - env.["state"], - message.["current_target"] - |) in - let* evm := process_message (| - message, - env - |) in + 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 : M unit := +Definition process_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -115,23 +121,25 @@ Definition process_message : M unit := Items containing execution specific objects *) (* TODO statement *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.touch_account (| - env.["state"], - message.["current_target"] - |) in + 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 *) - let* evm := execute_code (| - message, - env - |) in + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition execute_code : M unit := +Definition execute_code (message : Message) (env : Environment) : M Evm := (* Executes bytecode present in the `message`. @@ -147,13 +155,19 @@ Definition execute_code : M unit := evm: `ethereum.vm.EVM` Items containing execution specific objects *) - let* code := message.["code"] in - let* valid_jump_destinations := runtime.get_valid_jump_destinations (| - code - |) in - let* evm := Evm (| - - |) in + 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.v b/coq/ethereum/muir_glacier/vm/memory.v index 94b6a44639..88b516318f 100644 --- a/coq/ethereum/muir_glacier/vm/memory.v +++ b/coq/ethereum/muir_glacier/vm/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.byte. -Definition memory_write : M unit := +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := (* Writes to memory. @@ -30,9 +31,9 @@ Definition memory_write : M unit := Data to write to memory. *) (* TODO assignment *) + M.pure tt. - -Definition memory_read_bytes : M unit := +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := (* Read bytes from memory. @@ -51,9 +52,9 @@ Definition memory_read_bytes : M unit := Data read from memory. *) (* TODO statement *) + M.pure tt. - -Definition buffer_read : M unit := +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := (* Read bytes from a buffer. Padding with zeros if necessary. @@ -72,4 +73,4 @@ Definition buffer_read : M unit := Data read from memory. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/__init__.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/__init__.v index 74fc41487e..1e500955af 100644 --- a/coq/ethereum/muir_glacier/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,4 +14,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require muir_glacier.utils.hexadecimal. +Require ethereum.muir_glacier.utils.hexadecimal. diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.v index b1f35001eb..6c9beed797 100644 --- a/coq/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.v +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,12 +15,12 @@ Implementation of the ALT_BN128 precompiled contracts. Require ethereum_types.numeric. Require ethereum.crypto.alt_bn128. -Require muir_glacier.vm. -Require muir_glacier.vm.gas. -Require muir_glacier.vm.memory. -Require muir_glacier.vm.exceptions. +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 : M unit := +Definition alt_bn128_add (evm : Evm) : M unit := (* The ALT_BN128 addition precompiled contract. @@ -28,76 +29,96 @@ Definition alt_bn128_add : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* x1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x1_bytes - |) - |) in - let* y1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y1_bytes - |) - |) in + 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 *) - let* p := (* TODO expression *) in + do* M.assign "p" [[ + (* TODO expression *) in + ]] in (* TODO assignment *) + M.pure tt. - -Definition alt_bn128_mul : M unit := +Definition alt_bn128_mul (evm : Evm) : M unit := (* The ALT_BN128 multiplication precompiled contract. @@ -106,63 +127,77 @@ Definition alt_bn128_mul : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* n := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) (* TODO statement *) - let* p := p0.["mul_by"] (| - n - |) in + 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 : M unit := +Definition alt_bn128_pairing_check (evm : Evm) : M unit := (* The ALT_BN128 pairing check precompiled contract. @@ -171,17 +206,21 @@ Definition alt_bn128_pairing_check : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 (| + ethereum_types.numeric.Uint ~(| (* TODO expression *) |) - |) in + |) ]] in (* TODO statement *) - let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.v index f2119749e6..60142ab7ac 100644 --- a/coq/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.v +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,11 @@ Implementation of the `Blake2` precompiled contract. *) Require ethereum.crypto.blake2. -Require muir_glacier.vm. -Require muir_glacier.vm.gas. -Require muir_glacier.vm.exceptions. +Require ethereum.muir_glacier.vm. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.exceptions. -Definition blake2f : M unit := +Definition blake2f (evm : Evm) : M unit := (* Writes the Blake2 hash to output. @@ -26,16 +27,20 @@ Definition blake2f : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in (* TODO statement *) - let* blake2b := ethereum.crypto.blake2.Blake2b (| + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| - |) in + |) in + ]] in (* TODO assignment *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, (* TODO expression *) - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.v index 0b8c561a04..353937db20 100644 --- a/coq/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.v +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,11 +17,11 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require muir_glacier.vm. -Require muir_glacier.vm.gas. -Require muir_glacier.vm.memory. +Require ethereum.muir_glacier.vm. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.memory. -Definition ecrecover : M unit := +Definition ecrecover (evm : Evm) : M unit := (* Decrypts the address using elliptic curve DSA recovery mechanism and writes the address to output. @@ -30,64 +31,80 @@ Definition ecrecover : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* message_hash_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* message_hash := ethereum.crypto.hash.Hash32 (| - message_hash_bytes - |) in - let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + ethereum_types.numeric.U256 ~(| + 32 |) - |) - |) in - let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 + ]] 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 *) - let* address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/identity.v index 323b6dfe57..0b836f14de 100644 --- a/coq/ethereum/muir_glacier/vm/precompiled_contracts/identity.v +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/identity.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,10 @@ Implementation of the `IDENTITY` precompiled contract. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require muir_glacier.vm. -Require muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm. +Require ethereum.muir_glacier.vm.gas. -Definition identity : M unit := +Definition identity (evm : Evm) : M unit := (* Writes the message data to output. @@ -26,11 +27,15 @@ Definition identity : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/mapping.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/mapping.v index 3d48e2e1dd..c6c9c9920b 100644 --- a/coq/ethereum/muir_glacier/vm/precompiled_contracts/mapping.v +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/mapping.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Mapping of precompiled contracts their implementations. *) Require typing. -Require muir_glacier.fork_types. -Require muir_glacier.vm.precompiled_contracts.alt_bn128. -Require muir_glacier.vm.precompiled_contracts.blake2f. -Require muir_glacier.vm.precompiled_contracts.ecrecover. -Require muir_glacier.vm.precompiled_contracts.identity. -Require muir_glacier.vm.precompiled_contracts.modexp. -Require muir_glacier.vm.precompiled_contracts.ripemd160. -Require muir_glacier.vm.precompiled_contracts.sha256. +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.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/modexp.v index 588717745d..b239242ee1 100644 --- a/coq/ethereum/muir_glacier/vm/precompiled_contracts/modexp.v +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/modexp.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,100 +15,120 @@ Implementation of the `MODEXP` precompiled contract. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require muir_glacier.vm. -Require muir_glacier.vm.gas. -Require muir_glacier.vm.memory. +Require ethereum.muir_glacier.vm. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.memory. -Definition modexp : M unit := +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. *) - let* data := evm.["message"].["data"] in - let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) - |) in - let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 - let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* exp_start := (* TODO expression *) in - let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - min (| - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 |), - exp_length + ethereum_types.numeric.U256 ~(| + 32 + |) |) - |) - |) in - do* vm.gas.charge_gas (| + |) 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, - gas_cost (| - base_length, - modulus_length, - exp_length, - exp_head + 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 + |) ]] in (* TODO statement *) - let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - base_length - |) - |) in - let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - exp_length - |) - |) in - let* modulus_start := (* TODO expression *) in - let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - modulus_start, - modulus_length - |) - |) in + 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 : M unit := +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := (* Estimate the complexity of performing a modular exponentiation. @@ -126,18 +147,20 @@ Definition complexity : M unit := complexity : `Uint` Complexity of performing the operation. *) - let* max_length := max (| - ethereum_types.numeric.Uint (| - base_length - |), - ethereum_types.numeric.Uint (| - modulus_length - |) - |) in + 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 : M unit := +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := (* Calculate the number of iterations required to perform a modular exponentiation. @@ -160,9 +183,9 @@ Definition iterations : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition gas_cost : M unit := +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. @@ -188,15 +211,23 @@ Definition gas_cost : M unit := gas_cost : `Uint` Gas required for performing the operation. *) - let* multiplication_complexity := complexity (| - base_length, - modulus_length - |) in - let* iteration_count := iterations (| - exponent_length, - exponent_head - |) in - let* cost := (* TODO expression *) in - (* TODO statement *) + 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.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.v index bc5e73dd3c..fe2c66bbe6 100644 --- a/coq/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.v +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `RIPEMD160` precompiled contract. *) -Definition ripemd160 : M unit := +Definition ripemd160 (evm : Evm) : M unit := (* Writes the ripemd160 hash to output. @@ -22,21 +23,29 @@ Definition ripemd160 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 - let* hash_bytes := hashlib.["new"] (| - (* TODO expression *), - data - |).["digest"] (| - - |) in - let* padded_hash := left_pad_zero_bytes (| - hash_bytes, - (* TODO expression *) - |) in + |) ]] 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.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/sha256.v index da6972d411..3ba3ffe7aa 100644 --- a/coq/ethereum/muir_glacier/vm/precompiled_contracts/sha256.v +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/sha256.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `SHA256` precompiled contract. *) -Definition sha256 : M unit := +Definition sha256 (evm : Evm) : M unit := (* Writes the sha256 hash to output. @@ -22,11 +23,15 @@ Definition sha256 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/runtime.v b/coq/ethereum/muir_glacier/vm/runtime.v index 61466cb23b..3f6795dea4 100644 --- a/coq/ethereum/muir_glacier/vm/runtime.v +++ b/coq/ethereum/muir_glacier/vm/runtime.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Runtime Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Runtime related operations used while executing EVM code. Require typing. Require ethereum_types.numeric. -Require muir_glacier.vm.instructions. +Require ethereum.muir_glacier.vm.instructions. -Definition get_valid_jump_destinations : M unit := +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := (* Analyze the evm code to obtain the set of valid jump destinations. @@ -38,12 +39,16 @@ Definition get_valid_jump_destinations : M unit := valid_jump_destinations: `Set[Uint]` The set of valid jump destinations in the code. *) - let* valid_jump_destinations := set (| - - |) in - let* pc := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/muir_glacier/vm/stack.v index a6a417a566..09bf3b8bc4 100644 --- a/coq/ethereum/muir_glacier/vm/stack.v +++ b/coq/ethereum/muir_glacier/vm/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Implementation of the stack operators for the EVM. Require typing. Require ethereum_types.numeric. -Require muir_glacier.vm.exceptions. +Require ethereum.muir_glacier.vm.exceptions. -Definition pop : M unit := +Definition pop (stack : (* TODO type *)) : M U256 := (* Pops the top item off of `stack`. @@ -33,9 +34,9 @@ Definition pop : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition push : M unit := +Definition push (stack : (* TODO type *)) (value : U256) : M unit := (* Pushes `value` onto `stack`. @@ -50,4 +51,4 @@ Definition push : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/paris/__init__.v b/coq/ethereum/paris/__init__.v index e5f250b1c0..46293983bf 100644 --- a/coq/ethereum/paris/__init__.v +++ b/coq/ethereum/paris/__init__.v @@ -1,3 +1,4 @@ +(* 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 diff --git a/coq/ethereum/paris/blocks.v b/coq/ethereum/paris/blocks.v index fc5a46467f..6dc8830028 100644 --- a/coq/ethereum/paris/blocks.v +++ b/coq/ethereum/paris/blocks.v @@ -1,3 +1,4 @@ +(* 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 @@ -14,6 +15,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. -Require paris.fork_types. -Require paris.transactions. +Require ethereum.crypto.hash. +Require ethereum.paris.fork_types. +Require ethereum.paris.transactions. diff --git a/coq/ethereum/paris/bloom.v b/coq/ethereum/paris/bloom.v index 9a216ffea9..c7eb535ef5 100644 --- a/coq/ethereum/paris/bloom.v +++ b/coq/ethereum/paris/bloom.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Logs Bloom ^^^^^^^^^^^^^^^^^^^ @@ -19,10 +20,10 @@ eliminating blocks and receipts from their search. Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require paris.blocks. -Require paris.fork_types. +Require ethereum.paris.blocks. +Require ethereum.paris.fork_types. -Definition add_to_bloom : M unit := +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := (* Add a bloom entry to the bloom filter (`bloom`). @@ -37,13 +38,15 @@ Definition add_to_bloom : M unit := bloom_entry : An entry which is to be added to bloom filter. *) - let* hash := ethereum.crypto.hash.keccak256 (| - bloom_entry - |) in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition logs_bloom : M unit := +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := (* Obtain the logs bloom from a list of log entries. @@ -63,4 +66,4 @@ Definition logs_bloom : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/paris/exceptions.v b/coq/ethereum/paris/exceptions.v index 137ea143f6..9a313f6d0e 100644 --- a/coq/ethereum/paris/exceptions.v +++ b/coq/ethereum/paris/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Exceptions specific to this fork. *) diff --git a/coq/ethereum/paris/fork.v b/coq/ethereum/paris/fork.v index 31675ef605..e1bd556532 100644 --- a/coq/ethereum/paris/fork.v +++ b/coq/ethereum/paris/fork.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^ @@ -19,16 +20,18 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.exceptions. -Require paris.blocks. -Require paris.bloom. -Require paris.fork_types. -Require paris.state. -Require paris.transactions. -Require paris.trie. -Require paris.utils.message. -Require paris.vm.interpreter. - -Definition apply_fork : M unit := +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. @@ -48,9 +51,9 @@ Definition apply_fork : M unit := Upgraded block chain object for this hard fork. *) (* TODO statement *) + M.pure tt. - -Definition get_last_256_block_hashes : M unit := +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. @@ -70,22 +73,28 @@ Definition get_last_256_block_hashes : M unit := recent_block_hashes : `List[Hash32]` Hashes of the recent 256 blocks in order of increasing block number. *) - let* recent_blocks := (* TODO expression *) in - (* TODO statement *) - let* recent_block_hashes := (* TODO expression *) in - (* TODO statement *) - let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *).["header"] - |) - |) in - do* recent_block_hashes.["append"] (| - most_recent_block_hash - |) in - (* TODO statement *) - - -Definition state_transition : M unit := + 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. @@ -107,38 +116,42 @@ Definition state_transition : M unit := block : Block to apply to `chain`. *) - let* parent_header := (* TODO expression *).["header"] in - do* validate_header (| - block.["header"], - parent_header - |) in - (* TODO statement *) - let* apply_body_output := apply_body (| - chain.["state"], - get_last_256_block_hashes (| - chain - |), - block.["header"].["coinbase"], - block.["header"].["number"], - block.["header"].["base_fee_per_gas"], - block.["header"].["gas_limit"], - block.["header"].["timestamp"], - block.["header"].["prev_randao"], - block.["transactions"], - chain.["chain_id"] - |) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - do* chain.["blocks"].["append"] (| + 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 + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_base_fee_per_gas : M unit := +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. @@ -158,13 +171,15 @@ Definition calculate_base_fee_per_gas : M unit := base_fee_per_gas : `Uint` Base fee per gas for the block. *) - let* parent_gas_target := (* TODO expression *) in + do* M.assign "parent_gas_target" [[ + (* TODO expression *) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition validate_header : M unit := +Definition validate_header (header : Header) (parent_header : Header) : M unit := (* Verifies a block header. @@ -183,12 +198,14 @@ Definition validate_header : M unit := Parent Header of the header to check for correctness *) (* TODO statement *) - let* expected_base_fee_per_gas := calculate_base_fee_per_gas (| - header.["gas_limit"], - parent_header.["gas_limit"], - parent_header.["gas_used"], - parent_header.["base_fee_per_gas"] - |) in + 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 *) @@ -196,15 +213,17 @@ Definition validate_header : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* block_parent_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - parent_header - |) - |) in + 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 : M unit := +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. @@ -232,15 +251,17 @@ Definition check_transaction : M unit := If the transaction is not includable. *) (* TODO statement *) - let* sender_address := recover_sender (| - chain_id, - tx - |) in + 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 : M unit := +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. @@ -261,13 +282,15 @@ Definition make_receipt : M unit := receipt : The receipt for the transaction. *) - let* receipt := blocks.Receipt (| + do* M.assign "receipt" [[ + blocks.Receipt ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition apply_body : M unit := +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. @@ -310,19 +333,25 @@ Definition apply_body : M unit := apply_body_output : `ApplyBodyOutput` Output of applying the block body to the state. *) - let* gas_available := block_gas_limit in + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* block_gas_used := (* TODO expression *) in - let* block_logs_bloom := bloom.logs_bloom (| - block_logs - |) 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 process_transaction : M unit := +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := (* Execute a transaction against the provided environment. @@ -350,73 +379,107 @@ Definition process_transaction : M unit := Logs generated during execution. *) (* TODO statement *) - let* sender := env.["origin"] in - let* sender_account := state.get_account (| - env.["state"], - sender - |) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* effective_gas_fee := (* TODO expression *) in - let* gas := (* TODO expression *) in - do* state.increment_nonce (| - env.["state"], - sender - |) in - let* sender_balance_after_gas_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - ethereum_types.numeric.U256 (| - sender_balance_after_gas_fee - |) - |) in - let* preaccessed_addresses := set (| - - |) in - let* preaccessed_storage_keys := set (| - - |) in - (* TODO statement *) - let* message := utils.message.prepare_message (| - sender, - tx.["to"], - tx.["value"], - tx.["data"], - gas, - env - |) in - let* output := vm.interpreter.process_message_call (| - message, - env - |) in - let* gas_used := (* TODO expression *) in - let* gas_refund := min (| - (* TODO expression *), - ethereum_types.numeric.Uint (| - output.["refund_counter"] + 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 - let* gas_refund_amount := (* TODO expression *) in - let* priority_fee_per_gas := (* TODO expression *) in - let* transaction_fee := (* TODO expression *) in - let* total_gas_used := (* TODO expression *) in - let* sender_balance_after_refund := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - sender_balance_after_refund - |) in - let* coinbase_balance_after_mining_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - - -Definition validate_transaction : M unit := + |) ]] 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. @@ -444,9 +507,9 @@ Definition validate_transaction : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition calculate_intrinsic_cost : M unit := +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := (* Calculates the gas that is charged before execution is started. @@ -469,15 +532,19 @@ Definition calculate_intrinsic_cost : M unit := verified : `ethereum.base_types.Uint` The intrinsic cost of the transaction. *) - let* data_cost := (* TODO expression *) in + do* M.assign "data_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) - let* access_list_cost := (* TODO expression *) in + do* M.assign "access_list_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition recover_sender : M unit := +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := (* Extracts the sender address from a transaction. @@ -504,9 +571,9 @@ Definition recover_sender : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_pre155 : M unit := +Definition signing_hash_pre155 (tx : LegacyTransaction) : M Hash32 := (* Compute the hash of a transaction used in a legacy (pre EIP 155) signature. @@ -521,9 +588,9 @@ Definition signing_hash_pre155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_155 : M unit := +Definition signing_hash_155 (tx : LegacyTransaction) (chain_id : U64) : M Hash32 := (* Compute the hash of a transaction used in a EIP 155 signature. @@ -540,9 +607,9 @@ Definition signing_hash_155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_2930 : M unit := +Definition signing_hash_2930 (tx : AccessListTransaction) : M Hash32 := (* Compute the hash of a transaction used in a EIP 2930 signature. @@ -557,9 +624,9 @@ Definition signing_hash_2930 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_1559 : M unit := +Definition signing_hash_1559 (tx : FeeMarketTransaction) : M Hash32 := (* Compute the hash of a transaction used in a EIP 1559 signature. @@ -574,9 +641,9 @@ Definition signing_hash_1559 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition compute_header_hash : M unit := +Definition compute_header_hash (header : Header) : M Hash32 := (* Computes the hash of a block header. @@ -609,9 +676,9 @@ Definition compute_header_hash : M unit := Hash of the header. *) (* TODO statement *) + M.pure tt. - -Definition check_gas_limit : M unit := +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := (* Validates the gas limit for a block. @@ -639,9 +706,11 @@ Definition check_gas_limit : M unit := check : `bool` True if gas limit constraints are satisfied, False otherwise. *) - let* max_adjustment_delta := (* TODO expression *) in + 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.v b/coq/ethereum/paris/fork_types.v index 14de99d5e5..d84cffdf45 100644 --- a/coq/ethereum/paris/fork_types.v +++ b/coq/ethereum/paris/fork_types.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Types ^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. +Require ethereum.__init__. +Require ethereum.crypto.hash. -Definition encode_account : M unit := +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := (* Encode `Account` dataclass. @@ -26,4 +28,4 @@ Definition encode_account : M unit := encoded without providing a storage root. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/paris/state.v b/coq/ethereum/paris/state.v index 0f51028736..723275d350 100644 --- a/coq/ethereum/paris/state.v +++ b/coq/ethereum/paris/state.v @@ -1,3 +1,4 @@ +(* Generated *) (* State ^^^^^ @@ -22,10 +23,10 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require paris.fork_types. -Require paris.trie. +Require ethereum.paris.fork_types. +Require ethereum.paris.trie. -Definition close_state : M unit := +Definition close_state (state : State) : M unit := (* Free resources held by the state. Used by optimized implementations to release file descriptors. @@ -34,9 +35,9 @@ Definition close_state : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition begin_transaction : M unit := +Definition begin_transaction (state : State) : M unit := (* Start a state transaction. @@ -48,12 +49,12 @@ Definition begin_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition commit_transaction : M unit := +Definition commit_transaction (state : State) : M unit := (* Commit a state transaction. @@ -62,13 +63,13 @@ Definition commit_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["pop"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition rollback_transaction : M unit := +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. @@ -80,9 +81,9 @@ Definition rollback_transaction : M unit := *) (* TODO assignment *) (* TODO statement *) + M.pure tt. - -Definition get_account : M unit := +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. @@ -102,14 +103,16 @@ Definition get_account : M unit := account : `Account` Account at address. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition get_account_optional : M unit := +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. @@ -126,14 +129,16 @@ Definition get_account_optional : M unit := account : `Account` Account at address. *) - let* account := trie.trie_get (| - state.["_main_trie"], - address - |) in + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition set_account : M unit := +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()`). @@ -147,14 +152,14 @@ Definition set_account : M unit := account : `Account` Account to set at address. *) - do* trie.trie_set (| - state.["_main_trie"], + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), address, account - |) in + |) ]] in + M.pure tt. - -Definition destroy_account : M unit := +Definition destroy_account (state : State) (address : Address) : M unit := (* Completely remove the account at `address` and all of its storage. @@ -169,18 +174,18 @@ Definition destroy_account : M unit := address : `Address` Address of account to destroy. *) - do* destroy_storage (| + do* [[ M.get_local ~(| "destroy_storage" |) ~(| state, address - |) in - do* set_account (| + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - (* TODO expression *) - |) in + tt + |) ]] in + M.pure tt. - -Definition destroy_storage : M unit := +Definition destroy_storage (state : State) (address : Address) : M unit := (* Completely remove the storage at `address`. @@ -192,9 +197,9 @@ Definition destroy_storage : M unit := Address of account whose storage is to be deleted. *) (* TODO statement *) + M.pure tt. - -Definition mark_account_created : M unit := +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 @@ -211,12 +216,12 @@ Definition mark_account_created : M unit := address : `Address` Address of the account that has been created. *) - do* state.["created_accounts"].["add"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| address - |) in - + |) ]] in + M.pure tt. -Definition get_storage : M unit := +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. @@ -235,19 +240,23 @@ Definition get_storage : M unit := value : `U256` Value at the key. *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition set_storage : M unit := +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. @@ -264,19 +273,21 @@ Definition set_storage : M unit := Value to set at the key. *) (* TODO statement *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - do* trie.trie_set (| - trie, + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), key, value - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition storage_root : M unit := +Definition storage_root (state : State) (address : Address) : M Root := (* Calculate the storage root of an account. @@ -294,9 +305,9 @@ Definition storage_root : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition state_root : M unit := +Definition state_root (state : State) : M Root := (* Calculate the state root. @@ -313,9 +324,9 @@ Definition state_root : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition account_exists : M unit := +Definition account_exists (state : State) (address : Address) : M bool := (* Checks if an account exists in the state trie @@ -332,9 +343,9 @@ Definition account_exists : M unit := True if account exists in the state trie, False otherwise *) (* TODO statement *) + M.pure tt. - -Definition account_has_code_or_nonce : M unit := +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := (* Checks if an account has non zero nonce or non empty code @@ -351,14 +362,16 @@ Definition account_has_code_or_nonce : M unit := True if if an account has non zero nonce or non empty code, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_empty : M unit := +Definition is_account_empty (state : State) (address : Address) : M bool := (* Checks if an account has zero nonce, empty code and zero balance. @@ -375,14 +388,16 @@ Definition is_account_empty : M unit := True if if an account has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition account_exists_and_is_empty : M unit := +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. @@ -400,14 +415,16 @@ Definition account_exists_and_is_empty : M unit := True if an account exists and has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_alive : M unit := +Definition is_account_alive (state : State) (address : Address) : M bool := (* Check whether is an account is both in the state and non empty. @@ -423,49 +440,51 @@ Definition is_account_alive : M unit := is_alive : `bool` True if the account is alive. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition modify_state : M unit := +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := (* Modify an `Account` in the `State`. *) - do* set_account (| + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - ethereum_types.frozen.modify (| - get_account (| + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| state, address |), f |) - |) in - + |) ]] in + M.pure tt. -Definition move_ether : M unit := +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := (* Move funds between accounts. *) (* TODO statement *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, sender_address, - reduce_sender_balance - |) in - do* modify_state (| + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| state, recipient_address, - increase_recipient_balance - |) in + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. - -Definition set_account_balance : M unit := +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := (* Sets the balance of an account. @@ -481,14 +500,14 @@ Definition set_account_balance : M unit := The amount that needs to set in balance. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - set_balance - |) in - + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. -Definition touch_account : M unit := +Definition touch_account (state : State) (address : Address) : M unit := (* Initializes an account to state. @@ -501,9 +520,9 @@ Definition touch_account : M unit := The address of the account that need to initialised. *) (* TODO statement *) + M.pure tt. - -Definition increment_nonce : M unit := +Definition increment_nonce (state : State) (address : Address) : M unit := (* Increments the nonce of an account. @@ -516,14 +535,14 @@ Definition increment_nonce : M unit := Address of the account whose nonce needs to be incremented. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_nonce - |) in - + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. -Definition set_code : M unit := +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := (* Sets Account code. @@ -539,14 +558,14 @@ Definition set_code : M unit := The bytecode that needs to be set. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - write_code - |) in - + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. -Definition get_storage_original : M unit := +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 @@ -563,10 +582,12 @@ Definition get_storage_original : M unit := *) (* TODO statement *) (* TODO assignment *) - let* original_account_trie := original_trie.["get"] (| - address - |) in + 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.v b/coq/ethereum/paris/transactions.v index 28f2796b42..1dee19f5cc 100644 --- a/coq/ethereum/paris/transactions.v +++ b/coq/ethereum/paris/transactions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, @@ -9,19 +10,20 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require paris.exceptions. -Require paris.fork_types. +Require ethereum.__init__. +Require ethereum.paris.exceptions. +Require ethereum.paris.fork_types. -Definition encode_transaction : M unit := +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 : M unit := +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.v b/coq/ethereum/paris/trie.v index 548de91e1c..6b8953f256 100644 --- a/coq/ethereum/paris/trie.v +++ b/coq/ethereum/paris/trie.v @@ -1,3 +1,4 @@ +(* Generated *) (* State Trie ^^^^^^^^^^ @@ -14,7 +15,7 @@ The state trie is the structure responsible for storing *) -Definition encode_internal_node : M unit := +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 @@ -35,22 +36,24 @@ Definition encode_internal_node : M unit := *) (* TODO statement *) (* TODO statement *) - let* encoded := rlp.["encode"] (| - unencoded - |) in + 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 : M unit := +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 : M unit := +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. @@ -66,9 +69,9 @@ Definition copy_trie : M unit := A copy of the trie. *) (* TODO statement *) + M.pure tt. - -Definition trie_set : M unit := +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := (* Stores an item in a Merkle Trie. @@ -85,9 +88,9 @@ Definition trie_set : M unit := Node to insert at `key`. *) (* TODO statement *) + M.pure tt. - -Definition trie_get : M unit := +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := (* Gets an item from the Merkle Trie. @@ -106,17 +109,17 @@ Definition trie_get : M unit := Node at `key` in the trie. *) (* TODO statement *) + M.pure tt. - -Definition common_prefix_length : M unit := +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 : M unit := +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := (* Compresses nibble-list into a standard byte array with a flag. @@ -150,14 +153,16 @@ Definition nibble_list_to_compact : M unit := compressed : `bytearray` Compact byte array. *) - let* compact := bytearray (| + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition bytes_to_nibble_list : M unit := +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := (* Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). @@ -171,14 +176,16 @@ Definition bytes_to_nibble_list : M unit := nibble_list : `Bytes` The `Bytes` in nibble-list format. *) - let* nibble_list := bytearray (| - (* TODO expression *) - |) in + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _prepare_trie : M unit := +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. @@ -199,9 +206,9 @@ Definition _prepare_trie : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition root : M unit := +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := (* Computes the root of a modified merkle patricia trie (MPT). @@ -219,22 +226,26 @@ Definition root : M unit := root : `.fork_types.Root` MPT root of the underlying key-value pairs. *) - let* obj := _prepare_trie (| - trie, - get_storage_root - |) in - let* root_node := encode_internal_node (| - patricialize (| - obj, - Uint (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) + M.pure tt. - -Definition patricialize : M unit := +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := (* Structural composition function. @@ -254,21 +265,29 @@ Definition patricialize : M unit := Root node of `obj`. *) (* TODO statement *) - let* arbitrary_key := next (| - iter (| - obj - |) - |) in + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in (* TODO statement *) - let* substring := (* TODO expression *) in - let* prefix_length := len (| - substring - |) in + 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 *) - let* value := (* TODO expression *) in + do* M.assign "value" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/paris/utils/__init__.v b/coq/ethereum/paris/utils/__init__.v index beff4482b1..7f30fe939b 100644 --- a/coq/ethereum/paris/utils/__init__.v +++ b/coq/ethereum/paris/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions unique to this particular fork. *) diff --git a/coq/ethereum/paris/utils/address.v b/coq/ethereum/paris/utils/address.v index eee092b436..53e8bdf381 100644 --- a/coq/ethereum/paris/utils/address.v +++ b/coq/ethereum/paris/utils/address.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,9 +19,10 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require paris.fork_types. +Require ethereum.__init__. +Require ethereum.paris.fork_types. -Definition to_address : M unit := +Definition to_address (data : (* TODO type *)) : M Address := (* Convert a Uint or U256 value to a valid address (20 bytes). @@ -35,9 +37,9 @@ Definition to_address : M unit := The obtained address. *) (* TODO statement *) + M.pure tt. - -Definition compute_contract_address : M unit := +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := (* Computes address of the new account that needs to be created. @@ -54,20 +56,26 @@ Definition compute_contract_address : M unit := address: `Address` The computed address of the new account. *) - let* computed_address := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *) - |) - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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 : M unit := +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. @@ -86,14 +94,22 @@ Definition compute_create2_contract_address : M unit := address: `ethereum.paris.fork_types.Address` The computed address of the new account. *) - let* preimage := (* TODO expression *) in - let* computed_address := ethereum.crypto.hash.keccak256 (| - preimage - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/paris/utils/hexadecimal.v index 6903617d0b..b2b568d375 100644 --- a/coq/ethereum/paris/utils/hexadecimal.v +++ b/coq/ethereum/paris/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Paris types. *) Require ethereum.utils.hexadecimal. -Require paris.fork_types. +Require ethereum.paris.fork_types. -Definition hex_to_root : M unit := +Definition hex_to_root (hex_string : str) : M Root := (* Convert hex string to trie root. @@ -31,9 +32,9 @@ Definition hex_to_root : M unit := Trie root obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bloom : M unit := +Definition hex_to_bloom (hex_string : str) : M Bloom := (* Convert hex string to bloom. @@ -48,9 +49,9 @@ Definition hex_to_bloom : M unit := Bloom obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_address : M unit := +Definition hex_to_address (hex_string : str) : M Address := (* Convert hex string to Address (20 bytes). @@ -65,4 +66,4 @@ Definition hex_to_address : M unit := The address obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/paris/utils/message.v b/coq/ethereum/paris/utils/message.v index 3b5a529a5b..784037d71c 100644 --- a/coq/ethereum/paris/utils/message.v +++ b/coq/ethereum/paris/utils/message.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For The Message Data-structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,13 +17,13 @@ specification. Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require paris.fork_types. -Require paris.state. -Require paris.vm. -Require paris.vm.precompiled_contracts.mapping. -Require paris.utils.address. +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 : M unit := +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. @@ -61,22 +62,24 @@ Definition prepare_message : M unit := Items containing contract creation or message call specific data. *) (* TODO statement *) - let* accessed_addresses := set (| + do* M.assign "accessed_addresses" [[ + M.get_local ~(| "set" |) ~(| - |) in - do* accessed_addresses.["add"] (| - current_target - |) in - do* accessed_addresses.["add"] (| + |) 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* accessed_addresses.["update"] (| - vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS.["keys"] (| + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS, "keys" |) ~(| |) - |) in - do* accessed_addresses.["update"] (| + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| preaccessed_addresses - |) in + |) ]] in (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/paris/vm/__init__.v b/coq/ethereum/paris/vm/__init__.v index ee1ef60da7..1dc78dc046 100644 --- a/coq/ethereum/paris/vm/__init__.v +++ b/coq/ethereum/paris/vm/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,12 +19,12 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require paris.blocks. -Require paris.fork_types. -Require paris.state. -Require paris.vm.precompiled_contracts. +Require ethereum.paris.blocks. +Require ethereum.paris.fork_types. +Require ethereum.paris.state. +Require ethereum.paris.vm.precompiled_contracts. -Definition incorporate_child_on_success : M unit := +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of a successful `child_evm` into the parent `evm`. @@ -34,25 +35,31 @@ Definition incorporate_child_on_success : M unit := 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 *) - (* TODO statement *) - (* TODO statement *) - do* evm.["accounts_to_delete"].["update"] (| - child_evm.["accounts_to_delete"] - |) in - do* evm.["touched_accounts"].["update"] (| - child_evm.["touched_accounts"] - |) in - (* TODO statement *) - do* evm.["accessed_addresses"].["update"] (| - child_evm.["accessed_addresses"] - |) in - do* evm.["accessed_storage_keys"].["update"] (| - child_evm.["accessed_storage_keys"] - |) in + 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 : M unit := +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. @@ -65,5 +72,7 @@ Definition incorporate_child_on_error : M unit := *) (* TODO statement *) (* 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.v b/coq/ethereum/paris/vm/exceptions.v index 1784494410..47e26555d5 100644 --- a/coq/ethereum/paris/vm/exceptions.v +++ b/coq/ethereum/paris/vm/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Exceptions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/paris/vm/gas.v b/coq/ethereum/paris/vm/gas.v index 526d353822..3085866d46 100644 --- a/coq/ethereum/paris/vm/gas.v +++ b/coq/ethereum/paris/vm/gas.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Gas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,9 +18,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.trace. Require ethereum.utils.numeric. -Require paris.vm.exceptions. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.exceptions. -Definition charge_gas : M unit := +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := (* Subtracts `amount` from `evm.gas_left`. @@ -31,18 +33,18 @@ Definition charge_gas : M unit := The amount of gas the current operation requires. *) - do* ethereum.trace.evm_trace (| + do* [[ ethereum.trace.evm_trace ~(| evm, - ethereum.trace.GasAndRefund (| - int (| + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| amount |) |) - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_memory_gas_cost : M unit := +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, @@ -58,14 +60,22 @@ Definition calculate_memory_gas_cost : M unit := total_gas_cost : `ethereum.base_types.Uint` The gas cost for storing data in memory. *) - let* size_in_words := (* TODO expression *) in - let* linear_cost := (* TODO expression *) in - let* quadratic_cost := (* TODO expression *) in - let* total_gas_cost := (* TODO expression *) in + 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 : M unit := +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := (* Calculates the gas amount to extend memory @@ -81,22 +91,28 @@ Definition calculate_gas_extend_memory : M unit := ------- extend_memory: `ExtendMemory` *) - let* size_to_extend := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* to_be_paid := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* current_size := ethereum_types.numeric.Uint (| - len (| - memory - |) - |) in + 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 : M unit := +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. @@ -122,18 +138,22 @@ Definition calculate_message_call_gas : M unit := ------- message_call_gas: `MessageCallGas` *) - let* call_stipend := (* TODO expression *) in + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* gas := min (| - gas, - max_message_call_gas (| - (* TODO expression *) - |) - |) in + 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 : M unit := +Definition max_message_call_gas (gas : Uint) : M Uint := (* Calculates the maximum gas that is allowed for making a message call @@ -148,4 +168,4 @@ Definition max_message_call_gas : M unit := The maximum gas allowed for making the message-call. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/paris/vm/instructions/__init__.v b/coq/ethereum/paris/vm/instructions/__init__.v index b36b1ebfef..cbd7e7e63a 100644 --- a/coq/ethereum/paris/vm/instructions/__init__.v +++ b/coq/ethereum/paris/vm/instructions/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* EVM Instruction Encoding (Opcodes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/paris/vm/instructions/arithmetic.v b/coq/ethereum/paris/vm/instructions/arithmetic.v index 73f9cdd9d2..0e608dadc9 100644 --- a/coq/ethereum/paris/vm/instructions/arithmetic.v +++ b/coq/ethereum/paris/vm/instructions/arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,11 @@ Implementations of the EVM Arithmetic instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require paris.vm.gas. -Require paris.vm.stack. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.stack. -Definition add : M unit := +Definition add (evm : Evm) : M unit := (* Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -28,27 +30,37 @@ Definition add : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_add"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sub (evm : Evm) : M unit := (* Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -59,27 +71,37 @@ Definition sub : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_sub"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mul (evm : Evm) : M unit := (* Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -90,27 +112,37 @@ Definition mul : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_mul"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition div (evm : Evm) : M unit := (* Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -121,25 +153,33 @@ Definition div : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |) in - let* divisor := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - quotient - |) 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 : M unit := +Definition sdiv (evm : Evm) : M unit := (* Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -150,31 +190,39 @@ Definition sdiv : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* divisor := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - quotient + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mod : M unit := +Definition mod (evm : Evm) : M unit := (* Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -185,25 +233,33 @@ Definition mod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - remainder - |) in + |) ]] 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 : M unit := +Definition smod (evm : Evm) : M unit := (* Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -214,31 +270,39 @@ Definition smod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* y := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - remainder + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition addmod : M unit := +Definition addmod (evm : Evm) : M unit := (* Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -249,34 +313,44 @@ Definition addmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +Definition mulmod (evm : Evm) : M unit := (* Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -287,34 +361,44 @@ Definition mulmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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 : M unit := +Definition exp (evm : Evm) : M unit := (* Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -325,39 +409,53 @@ Definition exp : M unit := The current EVM frame. *) - let* base := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent_bits := exponent.["bit_length"] (| - - |) in - let* exponent_bytes := (* TODO expression *) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - pow (| - base, - exponent, - (* 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 - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition signextend : M unit := +Definition signextend (evm : Evm) : M unit := (* Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -368,20 +466,28 @@ Definition signextend : M unit := The current EVM frame. *) - let* byte_num := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/paris/vm/instructions/bitwise.v index b1cacf6745..cf138e1a25 100644 --- a/coq/ethereum/paris/vm/instructions/bitwise.v +++ b/coq/ethereum/paris/vm/instructions/bitwise.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Bitwise Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM bitwise instructions. *) Require ethereum_types.numeric. -Require paris.vm.gas. -Require paris.vm.stack. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.stack. -Definition bitwise_and : M unit := +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. @@ -27,24 +29,32 @@ Definition bitwise_and : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_or : M unit := +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. @@ -55,24 +65,32 @@ Definition bitwise_or : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_xor : M unit := +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. @@ -83,24 +101,32 @@ Definition bitwise_xor : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_not : M unit := +Definition bitwise_not (evm : Evm) : M unit := (* Bitwise NOT operation of the top element of the stack. Pushes the result back on the stack. @@ -111,21 +137,27 @@ Definition bitwise_not : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition get_byte : M unit := +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 @@ -137,25 +169,33 @@ Definition get_byte : M unit := The current EVM frame. *) - let* byte_index := stack.pop (| - evm.["stack"] - |) in - let* word := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -164,29 +204,37 @@ Definition bitwise_shl : M unit := evm : The current EVM frame. *) - let* shift := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -195,25 +243,33 @@ Definition bitwise_shr : M unit := evm : The current EVM frame. *) - let* shift := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -222,24 +278,32 @@ Definition bitwise_sar : M unit := evm : The current EVM frame. *) - let* shift := int (| - stack.pop (| - evm.["stack"] - |) - |) in - let* signed_value := stack.pop (| - evm.["stack"] - |).["to_signed"] (| + 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 - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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.v b/coq/ethereum/paris/vm/instructions/block.v index 8904838929..0b1cc9b5f7 100644 --- a/coq/ethereum/paris/vm/instructions/block.v +++ b/coq/ethereum/paris/vm/instructions/block.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Block Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM block instructions. *) Require ethereum_types.numeric. -Require paris.vm.gas. -Require paris.vm.stack. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.stack. -Definition block_hash : M unit := +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. @@ -33,27 +35,35 @@ Definition block_hash : M unit := :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError` If `evm.gas_left` is less than `20`. *) - let* block_number := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* max_block_number := (* TODO expression *) in + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition coinbase : M unit := +Definition coinbase (evm : Evm) : M unit := (* Push the current block's beneficiary address (address of the block miner) onto the stack. @@ -74,20 +84,24 @@ Definition coinbase : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["coinbase"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition timestamp : M unit := +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. @@ -108,18 +122,22 @@ Definition timestamp : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["env"].["time"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition number (evm : Evm) : M unit := (* Push the current block's number onto the stack. @@ -139,20 +157,24 @@ Definition number : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["number"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition prev_randao : M unit := +Definition prev_randao (evm : Evm) : M unit := (* Push the `prev_randao` value onto the stack. @@ -172,20 +194,24 @@ Definition prev_randao : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["prev_randao"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_limit : M unit := +Definition gas_limit (evm : Evm) : M unit := (* Push the current block's gas limit onto the stack. @@ -205,20 +231,24 @@ Definition gas_limit : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_limit"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition chain_id : M unit := +Definition chain_id (evm : Evm) : M unit := (* Push the chain id onto the stack. @@ -235,15 +265,19 @@ Definition chain_id : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["chain_id"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/paris/vm/instructions/comparison.v index de04583d9c..31e39f4445 100644 --- a/coq/ethereum/paris/vm/instructions/comparison.v +++ b/coq/ethereum/paris/vm/instructions/comparison.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Comparison Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM Comparison instructions. *) Require ethereum_types.numeric. -Require paris.vm.gas. -Require paris.vm.stack. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.stack. -Definition less_than : M unit := +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. @@ -27,27 +29,37 @@ Definition less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_less_than : M unit := + |) ]] 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. @@ -57,31 +69,41 @@ Definition signed_less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition greater_than : M unit := + |) ]] 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. @@ -92,27 +114,37 @@ Definition greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_greater_than : M unit := + |) ]] 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. @@ -122,31 +154,41 @@ Definition signed_greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition equal : M unit := + |) ]] 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. @@ -157,27 +199,37 @@ Definition equal : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition is_zero : M unit := + |) ]] 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. @@ -188,19 +240,27 @@ Definition is_zero : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/paris/vm/instructions/control_flow.v index 5bb7f0c9e8..c104e50c98 100644 --- a/coq/ethereum/paris/vm/instructions/control_flow.v +++ b/coq/ethereum/paris/vm/instructions/control_flow.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Control Flow Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM control flow instructions. *) Require ethereum_types.numeric. -Require paris.vm.gas. -Require paris.vm.exceptions. -Require paris.vm.stack. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.exceptions. +Require ethereum.paris.vm.stack. -Definition stop : M unit := +Definition stop (evm : Evm) : M unit := (* Stop further execution of EVM code. @@ -29,10 +31,14 @@ Definition stop : M unit := (* TODO statement *) (* TODO statement *) (* TODO assignment *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jump : M unit := +Definition jump (evm : Evm) : M unit := (* Alter the program counter to the location specified by the top of the stack. @@ -43,20 +49,22 @@ Definition jump : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition jumpi : M unit := +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 @@ -68,23 +76,27 @@ Definition jumpi : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* conditional_value := stack.pop (| - evm.["stack"] - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition pc : M unit := +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. @@ -96,20 +108,24 @@ Definition pc : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["pc"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_left : M unit := +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. @@ -121,20 +137,24 @@ Definition gas_left : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["gas_left"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jumpdest : M unit := +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 @@ -147,10 +167,14 @@ Definition jumpdest : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_JUMPDEST - |) in - (* TODO statement *) + |) ]] 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.v b/coq/ethereum/paris/vm/instructions/environment.v index 09fedbff2f..62f70fc204 100644 --- a/coq/ethereum/paris/vm/instructions/environment.v +++ b/coq/ethereum/paris/vm/instructions/environment.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,15 +16,16 @@ Implementations of the EVM environment related instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require paris.fork_types. -Require paris.state. -Require paris.utils.address. -Require paris.vm.memory. -Require paris.vm.exceptions. -Require paris.vm.gas. -Require paris.vm.stack. - -Definition address : M unit := +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. @@ -34,20 +36,24 @@ Definition address : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["current_target"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition balance : M unit := +Definition balance (evm : Evm) : M unit := (* Pushes the balance of the given account onto the stack. @@ -57,24 +63,32 @@ Definition balance : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] + 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 - (* TODO statement *) - let* balance := state.get_account (| - evm.["env"].["state"], - address - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition origin : M unit := +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. @@ -86,20 +100,24 @@ Definition origin : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["origin"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition caller : M unit := +Definition caller (evm : Evm) : M unit := (* Pushes the address of the caller onto the stack. @@ -110,20 +128,24 @@ Definition caller : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["caller"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition callvalue : M unit := +Definition callvalue (evm : Evm) : M unit := (* Push the value (in wei) sent with the call onto the stack. @@ -134,18 +156,22 @@ Definition callvalue : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["message"].["value"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition calldataload (evm : Evm) : M unit := (* Push a word (32 bytes) of the input data belonging to the current environment onto the stack. @@ -156,30 +182,38 @@ Definition calldataload : M unit := The current EVM frame. *) - let* start_index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - start_index, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] 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* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - value + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 |) - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition calldatasize : M unit := +Definition calldatasize (evm : Evm) : M unit := (* Push the size of input data in current environment onto the stack. @@ -190,22 +224,26 @@ Definition calldatasize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["message"].["data"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition calldatacopy : M unit := +Definition calldatacopy (evm : Evm) : M unit := (* Copy a portion of the input data in current environment to memory. @@ -218,40 +256,60 @@ Definition calldatacopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* data_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - data_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition codesize (evm : Evm) : M unit := (* Push the size of code running in current environment onto the stack. @@ -262,22 +320,26 @@ Definition codesize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["code"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition codecopy : M unit := +Definition codecopy (evm : Evm) : M unit := (* Copy a portion of the code in current environment to memory. @@ -290,40 +352,60 @@ Definition codecopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["code"], - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition gasprice (evm : Evm) : M unit := (* Push the gas price used in current environment onto the stack. @@ -334,20 +416,24 @@ Definition gasprice : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_price"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition extcodesize : M unit := +Definition extcodesize (evm : Evm) : M unit := (* Push the code size of a given account onto the stack. @@ -357,28 +443,36 @@ Definition extcodesize : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - (* TODO statement *) - let* codesize := ethereum_types.numeric.U256 (| - len (| - state.get_account (| - evm.["env"].["state"], - address - |).["code"] + 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 - do* stack.push (| - evm.["stack"], - codesize - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition extcodecopy : M unit := +Definition extcodecopy (evm : Evm) : M unit := (* Copy a portion of an account's code to memory. @@ -388,46 +482,70 @@ Definition extcodecopy : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - (* TODO statement *) - let* code := state.get_account (| - evm.["env"].["state"], - address - |).["code"] in - let* value := vm.memory.buffer_read (| - code, - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in + 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 : M unit := +Definition returndatasize (evm : Evm) : M unit := (* Pushes the size of the return data buffer onto the stack. @@ -437,22 +555,26 @@ Definition returndatasize : M unit := The current EVM frame. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["return_data"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition returndatacopy : M unit := +Definition returndatacopy (evm : Evm) : M unit := (* Copies data from the return data buffer code to memory @@ -461,37 +583,57 @@ Definition returndatacopy : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* return_data_start_position := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - (* TODO statement *) - let* value := (* TODO expression *) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in + |) ]] 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 : M unit := +Definition extcodehash (evm : Evm) : M unit := (* Returns the keccak256 hash of a contract’s bytecode Parameters @@ -499,25 +641,33 @@ Definition extcodehash : M unit := evm : The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] + 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 - (* TODO statement *) - let* account := state.get_account (| - evm.["env"].["state"], - address - |) in - (* TODO statement *) - do* stack.push (| - evm.["stack"], - codehash - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition self_balance : M unit := +Definition self_balance (evm : Evm) : M unit := (* Pushes the balance of the current address to the stack. @@ -528,22 +678,28 @@ Definition self_balance : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_FAST_STEP - |) in - let* balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition base_fee (evm : Evm) : M unit := (* Pushes the base fee of the current block on to the stack. @@ -554,15 +710,19 @@ Definition base_fee : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["base_fee_per_gas"] + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/paris/vm/instructions/keccak.v index a638f16e31..a56cf7ecab 100644 --- a/coq/ethereum/paris/vm/instructions/keccak.v +++ b/coq/ethereum/paris/vm/instructions/keccak.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Keccak Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM keccak instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require paris.vm.gas. -Require paris.vm.memory. -Require paris.vm.stack. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.memory. +Require ethereum.paris.vm.stack. -Definition keccak : M unit := +Definition keccak (evm : Evm) : M unit := (* Pushes to the stack the Keccak-256 hash of a region of memory. @@ -32,36 +34,56 @@ Definition keccak : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* word_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in - let* hash := ethereum.crypto.hash.keccak256 (| - data - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/paris/vm/instructions/log.v index 60917ddfff..2c4b57f004 100644 --- a/coq/ethereum/paris/vm/instructions/log.v +++ b/coq/ethereum/paris/vm/instructions/log.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Logging Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,13 +15,14 @@ Implementations of the EVM logging instructions. Require functools. Require ethereum_types.numeric. -Require paris.blocks. -Require paris.vm.exceptions. -Require paris.vm.gas. -Require paris.vm.memory. -Require paris.vm.stack. +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 : M unit := +Definition log_n (evm : Evm) (num_topics : U256) : M unit := (* Appends a log entry, having `num_topics` topics, to the evm logs. @@ -35,27 +37,43 @@ Definition log_n : M unit := The number of topics to be included in the log entry. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* topics := (* TODO expression *) in + 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 *) - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in (* TODO statement *) - let* log_entry := blocks.Log (| + do* M.assign "log_entry" [[ + blocks.Log ~(| - |) in + |) in + ]] in (* TODO assignment *) - (* 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/memory.v b/coq/ethereum/paris/vm/instructions/memory.v index a1a0dda6df..c134d6071b 100644 --- a/coq/ethereum/paris/vm/instructions/memory.v +++ b/coq/ethereum/paris/vm/instructions/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM Memory instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require paris.vm.gas. -Require paris.vm.memory. -Require paris.vm.stack. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.memory. +Require ethereum.paris.vm.stack. -Definition mstore : M unit := +Definition mstore (evm : Evm) : M unit := (* Stores a word to memory. This also expands the memory, if the memory is @@ -30,32 +32,44 @@ Definition mstore : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* memory.memory_write (| - evm.["memory"], - start_position, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mstore8 (evm : Evm) : M unit := (* Stores a byte to memory. This also expands the memory, if the memory is @@ -67,33 +81,47 @@ Definition mstore8 : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ (* TODO expression *) - |) in - do* memory.memory_write (| - evm.["memory"], - start_position, - normalized_bytes_value - |) in - (* TODO statement *) - + ]] 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 : M unit := +Definition mload (evm : Evm) : M unit := (* Load word from memory. @@ -103,35 +131,47 @@ Definition mload : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.memory_read_bytes (| - evm.["memory"], - start_position, - ethereum_types.numeric.U256 (| - (* 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 - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition msize : M unit := +Definition msize (evm : Evm) : M unit := (* Push the size of active memory in bytes onto the stack. @@ -142,17 +182,21 @@ Definition msize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["memory"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/paris/vm/instructions/stack.v index 091b7d3fb3..7c7a73c495 100644 --- a/coq/ethereum/paris/vm/instructions/stack.v +++ b/coq/ethereum/paris/vm/instructions/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM stack related instructions. Require functools. Require ethereum_types.numeric. -Require paris.vm.exceptions. -Require paris.vm.gas. -Require paris.vm.memory. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.exceptions. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.memory. -Definition pop : M unit := +Definition pop (evm : Evm) : M unit := (* Remove item from stack. @@ -28,18 +30,22 @@ Definition pop : M unit := The current EVM frame. *) - do* stack.["pop"] (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in + |) ]] in (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition push_n : M unit := +Definition push_n (evm : Evm) (num_bytes : int) : M unit := (* Pushes a N-byte immediate onto the stack. @@ -54,29 +60,33 @@ Definition push_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - evm.["code"], - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - num_bytes + |) ]] 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 - do* stack.["push"] (| - evm.["stack"], - data_to_push - |) in - (* TODO statement *) - - -Definition dup_n : M unit := + |) 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. @@ -91,20 +101,26 @@ Definition dup_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - let* data_to_duplicate := (* TODO expression *) in - do* stack.["push"] (| - evm.["stack"], - data_to_duplicate - |) 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 : M unit := +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. @@ -123,11 +139,15 @@ Definition swap_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - (* 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/storage.v b/coq/ethereum/paris/vm/instructions/storage.v index 4df30cb924..cdaea2ef59 100644 --- a/coq/ethereum/paris/vm/instructions/storage.v +++ b/coq/ethereum/paris/vm/instructions/storage.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Storage Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,12 +14,13 @@ Implementations of the EVM storage related instructions. *) Require ethereum_types.numeric. -Require paris.state. -Require paris.vm.exceptions. -Require paris.vm.gas. -Require paris.vm.stack. +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 : M unit := +Definition sload (evm : Evm) : M unit := (* Loads to the stack, the value corresponding to a certain key from the storage of the current account. @@ -29,25 +31,33 @@ Definition sload : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in + |) in + ]] in (* TODO statement *) - let* value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) 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 : M unit := +Definition sstore (evm : Evm) : M unit := (* Stores a value at a certain key in the current context's storage. @@ -57,41 +67,55 @@ Definition sstore : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in (* TODO statement *) - let* original_value := state.get_storage_original (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - let* current_value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - let* gas_cost := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in + M.get_local ~(| "gas_cost" |) + |) ]] in (* TODO statement *) - do* state.set_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key, - new_value - |) 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.v b/coq/ethereum/paris/vm/instructions/system.v index d5867e896f..1740ce8ae4 100644 --- a/coq/ethereum/paris/vm/instructions/system.v +++ b/coq/ethereum/paris/vm/instructions/system.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) System Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,57 +16,72 @@ Implementations of the EVM system related instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require paris.fork_types. -Require paris.state. -Require paris.utils.address. -Require paris.vm.exceptions. -Require paris.vm.gas. -Require paris.vm.memory. -Require paris.vm.stack. - -Definition generic_create : M unit := +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* evm.["accessed_addresses"].["add"] (| + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "add" |) ~(| contract_address - |) in - let* create_message_gas := gas.max_message_call_gas (| - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |) - |) in - (* TODO statement *) + |) ]] 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 *) - let* sender_address := evm.["message"].["current_target"] in - let* sender := state.get_account (| - evm.["env"].["state"], - sender_address - |) in - (* TODO statement *) - (* TODO statement *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) in - do* state.increment_nonce (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |) in - let* child_message := Message (| - - |) in - let* child_evm := process_create_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - - -Definition create : M unit := + 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. @@ -74,42 +90,58 @@ Definition create : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_contract_address (| - evm.["message"].["current_target"], - state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["nonce"] - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition create2 (evm : Evm) : M unit := (* Creates a new account with associated code. @@ -121,50 +153,70 @@ Definition create2 : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* salt := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* call_data_words := (* TODO expression *) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_create2_contract_address (| - evm.["message"].["current_target"], - salt, - memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size - |) in - (* TODO statement *) - + 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_ : M unit := +Definition return_ (evm : Evm) : M unit := (* Halts execution returning output data. @@ -173,66 +225,84 @@ Definition return_ : M unit := evm : The current EVM frame. *) - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) + |) ]] 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 : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_input_start_position, - memory_input_size - |) in - let* code := state.get_account (| - evm.["env"].["state"], - code_address - |).["code"] in - let* child_message := Message (| - - |) in - let* child_evm := process_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - let* actual_output_size := min (| - memory_output_size, - ethereum_types.numeric.U256 (| - len (| - child_evm.["output"] + 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 - do* memory.memory_write (| - evm.["memory"], + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), memory_output_start_position, (* TODO expression *) - |) in + |) ]] in + M.pure tt. - -Definition call : M unit := +Definition call (evm : Evm) : M unit := (* Message-call into an account. @@ -241,62 +311,92 @@ Definition call : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* create_gas_cost := (* TODO expression *) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition callcode (evm : Evm) : M unit := (* Message-call into this account with alternative account’s code. @@ -305,61 +405,91 @@ Definition callcode : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* to := evm.["message"].["current_target"] in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) - (* TODO statement *) - + |) ]] 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 : M unit := +Definition selfdestruct (evm : Evm) : M unit := (* Halt execution and register account for later deletion. @@ -368,49 +498,59 @@ Definition selfdestruct : M unit := evm : The current EVM frame. *) - let* beneficiary := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* gas_cost := gas.GAS_SELF_DESTRUCT in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - (* TODO statement *) - let* originator := evm.["message"].["current_target"] in - let* beneficiary_balance := state.get_account (| - evm.["env"].["state"], - beneficiary - |).["balance"] in - let* originator_balance := state.get_account (| - evm.["env"].["state"], - originator - |).["balance"] in - do* state.set_account_balance (| - evm.["env"].["state"], - beneficiary, + 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 (| - evm.["env"].["state"], - originator, - ethereum_types.numeric.U256 (| - (* 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* evm.["accounts_to_delete"].["add"] (| - originator - |) in + |) ]] 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 : M unit := +Definition delegatecall (evm : Evm) : M unit := (* Message-call into an account. @@ -419,67 +559,89 @@ Definition delegatecall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - access_gas_cost - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - evm.["message"].["value"], - evm.["message"].["caller"], - evm.["message"].["current_target"], - code_address, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition staticcall (evm : Evm) : M unit := (* Message-call into an account. @@ -488,69 +650,91 @@ Definition staticcall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - access_gas_cost - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - ethereum_types.numeric.U256 (| - (* TODO expression *) + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 |), - evm.["message"].["current_target"], - to, - to, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +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 @@ -559,27 +743,37 @@ Definition revert : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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, - extend_memory.["cost"] - |) in - (* TODO statement *) - let* output := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in + 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.v b/coq/ethereum/paris/vm/interpreter.v index 861ecc75a7..fa53be1727 100644 --- a/coq/ethereum/paris/vm/interpreter.v +++ b/coq/ethereum/paris/vm/interpreter.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Interpreter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +18,18 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.trace. -Require paris.blocks. -Require paris.fork_types. -Require paris.state. -Require paris.vm. -Require paris.vm.gas. -Require paris.vm.precompiled_contracts.mapping. -Require paris.vm.exceptions. -Require paris.vm.instructions. -Require paris.vm.runtime. - -Definition process_message_call : M unit := +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`. @@ -47,19 +49,21 @@ Definition process_message_call : M unit := *) (* TODO statement *) (* TODO statement *) - let* tx_end := ethereum.trace.TransactionEnd (| - (* TODO expression *), - evm.["output"], - evm.["error"] - |) in - do* ethereum.trace.evm_trace (| - evm, - tx_end - |) in + 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 : M unit := +Definition process_create_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -75,30 +79,32 @@ Definition process_create_message : M unit := evm: :py:class:`~ethereum.paris.vm.Evm` Items containing execution specific objects. *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.destroy_storage (| - env.["state"], - message.["current_target"] - |) in - do* state.mark_account_created (| - env.["state"], - message.["current_target"] - |) in - do* state.increment_nonce (| - env.["state"], - message.["current_target"] - |) in - let* evm := process_message (| - message, - env - |) in + 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 : M unit := +Definition process_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -115,23 +121,25 @@ Definition process_message : M unit := Items containing execution specific objects *) (* TODO statement *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.touch_account (| - env.["state"], - message.["current_target"] - |) in + 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 *) - let* evm := execute_code (| - message, - env - |) in + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition execute_code : M unit := +Definition execute_code (message : Message) (env : Environment) : M Evm := (* Executes bytecode present in the `message`. @@ -147,13 +155,19 @@ Definition execute_code : M unit := evm: `ethereum.vm.EVM` Items containing execution specific objects *) - let* code := message.["code"] in - let* valid_jump_destinations := runtime.get_valid_jump_destinations (| - code - |) in - let* evm := Evm (| - - |) in + 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.v b/coq/ethereum/paris/vm/memory.v index 94b6a44639..88b516318f 100644 --- a/coq/ethereum/paris/vm/memory.v +++ b/coq/ethereum/paris/vm/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.byte. -Definition memory_write : M unit := +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := (* Writes to memory. @@ -30,9 +31,9 @@ Definition memory_write : M unit := Data to write to memory. *) (* TODO assignment *) + M.pure tt. - -Definition memory_read_bytes : M unit := +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := (* Read bytes from memory. @@ -51,9 +52,9 @@ Definition memory_read_bytes : M unit := Data read from memory. *) (* TODO statement *) + M.pure tt. - -Definition buffer_read : M unit := +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := (* Read bytes from a buffer. Padding with zeros if necessary. @@ -72,4 +73,4 @@ Definition buffer_read : M unit := Data read from memory. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/paris/vm/precompiled_contracts/__init__.v b/coq/ethereum/paris/vm/precompiled_contracts/__init__.v index 80a08b3bf2..46a71b60f2 100644 --- a/coq/ethereum/paris/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/paris/vm/precompiled_contracts/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,4 +14,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require paris.utils.hexadecimal. +Require ethereum.paris.utils.hexadecimal. diff --git a/coq/ethereum/paris/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/paris/vm/precompiled_contracts/alt_bn128.v index 3273b06ff2..90ed0d3513 100644 --- a/coq/ethereum/paris/vm/precompiled_contracts/alt_bn128.v +++ b/coq/ethereum/paris/vm/precompiled_contracts/alt_bn128.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,12 +15,12 @@ Implementation of the ALT_BN128 precompiled contracts. Require ethereum_types.numeric. Require ethereum.crypto.alt_bn128. -Require paris.vm. -Require paris.vm.gas. -Require paris.vm.memory. -Require paris.vm.exceptions. +Require ethereum.paris.vm. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.memory. +Require ethereum.paris.vm.exceptions. -Definition alt_bn128_add : M unit := +Definition alt_bn128_add (evm : Evm) : M unit := (* The ALT_BN128 addition precompiled contract. @@ -28,76 +29,96 @@ Definition alt_bn128_add : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* x1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x1_bytes - |) - |) in - let* y1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y1_bytes - |) - |) in + 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 *) - let* p := (* TODO expression *) in + do* M.assign "p" [[ + (* TODO expression *) in + ]] in (* TODO assignment *) + M.pure tt. - -Definition alt_bn128_mul : M unit := +Definition alt_bn128_mul (evm : Evm) : M unit := (* The ALT_BN128 multiplication precompiled contract. @@ -106,63 +127,77 @@ Definition alt_bn128_mul : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* n := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) (* TODO statement *) - let* p := p0.["mul_by"] (| - n - |) in + 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 : M unit := +Definition alt_bn128_pairing_check (evm : Evm) : M unit := (* The ALT_BN128 pairing check precompiled contract. @@ -171,17 +206,21 @@ Definition alt_bn128_pairing_check : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 (| + ethereum_types.numeric.Uint ~(| (* TODO expression *) |) - |) in + |) ]] in (* TODO statement *) - let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/paris/vm/precompiled_contracts/blake2f.v index 3655e229ef..5042c50aca 100644 --- a/coq/ethereum/paris/vm/precompiled_contracts/blake2f.v +++ b/coq/ethereum/paris/vm/precompiled_contracts/blake2f.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,11 @@ Implementation of the `Blake2` precompiled contract. *) Require ethereum.crypto.blake2. -Require paris.vm. -Require paris.vm.gas. -Require paris.vm.exceptions. +Require ethereum.paris.vm. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.exceptions. -Definition blake2f : M unit := +Definition blake2f (evm : Evm) : M unit := (* Writes the Blake2 hash to output. @@ -26,16 +27,20 @@ Definition blake2f : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in (* TODO statement *) - let* blake2b := ethereum.crypto.blake2.Blake2b (| + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| - |) in + |) in + ]] in (* TODO assignment *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, (* TODO expression *) - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/paris/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/paris/vm/precompiled_contracts/ecrecover.v index e91c7a9c9f..04c9ebc232 100644 --- a/coq/ethereum/paris/vm/precompiled_contracts/ecrecover.v +++ b/coq/ethereum/paris/vm/precompiled_contracts/ecrecover.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,11 +17,11 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require paris.vm. -Require paris.vm.gas. -Require paris.vm.memory. +Require ethereum.paris.vm. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.memory. -Definition ecrecover : M unit := +Definition ecrecover (evm : Evm) : M unit := (* Decrypts the address using elliptic curve DSA recovery mechanism and writes the address to output. @@ -30,64 +31,80 @@ Definition ecrecover : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* message_hash_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* message_hash := ethereum.crypto.hash.Hash32 (| - message_hash_bytes - |) in - let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + ethereum_types.numeric.U256 ~(| + 32 |) - |) - |) in - let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 + ]] 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 *) - let* address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/paris/vm/precompiled_contracts/identity.v index c12960e71a..d90d95a7aa 100644 --- a/coq/ethereum/paris/vm/precompiled_contracts/identity.v +++ b/coq/ethereum/paris/vm/precompiled_contracts/identity.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,10 @@ Implementation of the `IDENTITY` precompiled contract. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require paris.vm. -Require paris.vm.gas. +Require ethereum.paris.vm. +Require ethereum.paris.vm.gas. -Definition identity : M unit := +Definition identity (evm : Evm) : M unit := (* Writes the message data to output. @@ -26,11 +27,15 @@ Definition identity : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/paris/vm/precompiled_contracts/mapping.v b/coq/ethereum/paris/vm/precompiled_contracts/mapping.v index f746acb2a9..07b1615a06 100644 --- a/coq/ethereum/paris/vm/precompiled_contracts/mapping.v +++ b/coq/ethereum/paris/vm/precompiled_contracts/mapping.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Mapping of precompiled contracts their implementations. *) Require typing. -Require paris.fork_types. -Require paris.vm.precompiled_contracts.alt_bn128. -Require paris.vm.precompiled_contracts.blake2f. -Require paris.vm.precompiled_contracts.ecrecover. -Require paris.vm.precompiled_contracts.identity. -Require paris.vm.precompiled_contracts.modexp. -Require paris.vm.precompiled_contracts.ripemd160. -Require paris.vm.precompiled_contracts.sha256. +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.v b/coq/ethereum/paris/vm/precompiled_contracts/modexp.v index b723c4a781..3ec8f5b2af 100644 --- a/coq/ethereum/paris/vm/precompiled_contracts/modexp.v +++ b/coq/ethereum/paris/vm/precompiled_contracts/modexp.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,100 +15,120 @@ Implementation of the `MODEXP` precompiled contract. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require paris.vm. -Require paris.vm.gas. -Require paris.vm.memory. +Require ethereum.paris.vm. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.memory. -Definition modexp : M unit := +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. *) - let* data := evm.["message"].["data"] in - let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) - |) in - let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 - let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* exp_start := (* TODO expression *) in - let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - min (| - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 |), - exp_length + ethereum_types.numeric.U256 ~(| + 32 + |) |) - |) - |) in - do* vm.gas.charge_gas (| + |) 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, - gas_cost (| - base_length, - modulus_length, - exp_length, - exp_head + 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 + |) ]] in (* TODO statement *) - let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - base_length - |) - |) in - let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - exp_length - |) - |) in - let* modulus_start := (* TODO expression *) in - let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - modulus_start, - modulus_length - |) - |) in + 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 : M unit := +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := (* Estimate the complexity of performing a modular exponentiation. @@ -126,19 +147,23 @@ Definition complexity : M unit := complexity : `Uint` Complexity of performing the operation. *) - let* max_length := max (| - ethereum_types.numeric.Uint (| - base_length - |), - ethereum_types.numeric.Uint (| - modulus_length - |) - |) in - let* words := (* TODO expression *) in + 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 : M unit := +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := (* Calculate the number of iterations required to perform a modular exponentiation. @@ -161,9 +186,9 @@ Definition iterations : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition gas_cost : M unit := +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. @@ -189,15 +214,23 @@ Definition gas_cost : M unit := gas_cost : `Uint` Gas required for performing the operation. *) - let* multiplication_complexity := complexity (| - base_length, - modulus_length - |) in - let* iteration_count := iterations (| - exponent_length, - exponent_head - |) in - let* cost := (* TODO expression *) in - (* TODO statement *) + 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.v b/coq/ethereum/paris/vm/precompiled_contracts/ripemd160.v index bc5e73dd3c..fe2c66bbe6 100644 --- a/coq/ethereum/paris/vm/precompiled_contracts/ripemd160.v +++ b/coq/ethereum/paris/vm/precompiled_contracts/ripemd160.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `RIPEMD160` precompiled contract. *) -Definition ripemd160 : M unit := +Definition ripemd160 (evm : Evm) : M unit := (* Writes the ripemd160 hash to output. @@ -22,21 +23,29 @@ Definition ripemd160 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 - let* hash_bytes := hashlib.["new"] (| - (* TODO expression *), - data - |).["digest"] (| - - |) in - let* padded_hash := left_pad_zero_bytes (| - hash_bytes, - (* TODO expression *) - |) in + |) ]] 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.v b/coq/ethereum/paris/vm/precompiled_contracts/sha256.v index da6972d411..3ba3ffe7aa 100644 --- a/coq/ethereum/paris/vm/precompiled_contracts/sha256.v +++ b/coq/ethereum/paris/vm/precompiled_contracts/sha256.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `SHA256` precompiled contract. *) -Definition sha256 : M unit := +Definition sha256 (evm : Evm) : M unit := (* Writes the sha256 hash to output. @@ -22,11 +23,15 @@ Definition sha256 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/paris/vm/runtime.v b/coq/ethereum/paris/vm/runtime.v index cb9d90bb93..4e79d9dd32 100644 --- a/coq/ethereum/paris/vm/runtime.v +++ b/coq/ethereum/paris/vm/runtime.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Runtime Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Runtime related operations used while executing EVM code. Require typing. Require ethereum_types.numeric. -Require paris.vm.instructions. +Require ethereum.paris.vm.instructions. -Definition get_valid_jump_destinations : M unit := +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := (* Analyze the evm code to obtain the set of valid jump destinations. @@ -38,12 +39,16 @@ Definition get_valid_jump_destinations : M unit := valid_jump_destinations: `Set[Uint]` The set of valid jump destinations in the code. *) - let* valid_jump_destinations := set (| - - |) in - let* pc := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/paris/vm/stack.v index 00cb979a94..5f42af2fee 100644 --- a/coq/ethereum/paris/vm/stack.v +++ b/coq/ethereum/paris/vm/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Implementation of the stack operators for the EVM. Require typing. Require ethereum_types.numeric. -Require paris.vm.exceptions. +Require ethereum.paris.vm.exceptions. -Definition pop : M unit := +Definition pop (stack : (* TODO type *)) : M U256 := (* Pops the top item off of `stack`. @@ -33,9 +34,9 @@ Definition pop : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition push : M unit := +Definition push (stack : (* TODO type *)) (value : U256) : M unit := (* Pushes `value` onto `stack`. @@ -50,4 +51,4 @@ Definition push : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/rlp.v b/coq/ethereum/rlp.v index 87c4e5c53a..65bcfe9f56 100644 --- a/coq/ethereum/rlp.v +++ b/coq/ethereum/rlp.v @@ -1,3 +1,4 @@ +(* Generated *) (* .. _rlp: @@ -21,7 +22,7 @@ Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.exceptions. -Definition encode : M unit := +Definition encode (raw_data : Extended) : M Bytes := (* Encodes `raw_data` into a sequence of bytes using RLP. @@ -37,9 +38,9 @@ Definition encode : M unit := The RLP encoded bytes representing `raw_data`. *) (* TODO statement *) + M.pure tt. - -Definition encode_bytes : M unit := +Definition encode_bytes (raw_bytes : Bytes) : M Bytes := (* Encodes `raw_bytes`, a sequence of bytes, using RLP. @@ -53,13 +54,15 @@ Definition encode_bytes : M unit := encoded : `ethereum.base_types.Bytes` The RLP encoded bytes representing `raw_bytes`. *) - let* len_raw_data := len (| - raw_bytes - |) in + do* M.assign "len_raw_data" [[ + M.get_local ~(| "len" |) ~(| + raw_bytes + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition encode_sequence : M unit := +Definition encode_sequence (raw_sequence : (* TODO type *)) : M Bytes := (* Encodes a list of RLP encodable objects (`raw_sequence`) using RLP. @@ -73,16 +76,20 @@ Definition encode_sequence : M unit := encoded : `ethereum.base_types.Bytes` The RLP encoded bytes representing `raw_sequence`. *) - let* joined_encodings := get_joined_encodings (| - raw_sequence - |) in - let* len_joined_encodings := len (| - joined_encodings - |) in - (* TODO statement *) - - -Definition get_joined_encodings : M unit := + 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. @@ -99,9 +106,9 @@ Definition get_joined_encodings : M unit := raw_sequence. *) (* TODO statement *) + M.pure tt. - -Definition decode : M unit := +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. @@ -118,9 +125,9 @@ Definition decode : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition decode_to : M unit := +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]`. @@ -137,88 +144,108 @@ Definition decode_to : M unit := decoded_data : `U` Object decoded from `encoded_data`. *) - let* decoded := decode (| - encoded_data - |) in + do* M.assign "decoded" [[ + M.get_local ~(| "decode" |) ~(| + encoded_data + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition _deserialize_to : M unit := +Definition _deserialize_to (class_ : (* TODO type *)) (value : Simple) : M U := (* TODO statement *) + M.pure tt. - -Definition _deserialize_to : M unit := +Definition _deserialize_to (class_ : object) (value : Simple) : M Extended := (* TODO statement *) + M.pure tt. - -Definition _deserialize_to : M unit := +Definition _deserialize_to (class_ : object) (value : Simple) : M Extended := (* TODO statement *) + M.pure tt. - -Definition _deserialize_to_dataclass : M unit := +Definition _deserialize_to_dataclass (cls : (* TODO type *)) (decoded : Simple) : M U := (* TODO statement *) - let* hints := typing.get_type_hints (| - cls - |) in - let* target_fields := dataclasses.fields (| - cls - |) in + 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 *) - let* result := cls (| + do* M.assign "result" [[ + cls ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _deserialize_to_bool : M unit := +Definition _deserialize_to_bool (value : Simple) : M bool := (* TODO statement *) + M.pure tt. - -Definition _deserialize_to_bytes : M unit := +Definition _deserialize_to_bytes (class_ : (* TODO type *)) (value : Simple) : M (* TODO type *) := (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _deserialize_to_uint : M unit := +Definition _deserialize_to_uint (class_ : (* TODO type *)) (decoded : Simple) : M (* TODO type *) := (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _deserialize_to_annotation : M unit := - let* origin := typing.get_origin (| - annotation - |) in +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 : M unit := - let* arguments := typing.get_args (| - annotation - |) in - let* successes := (* TODO expression *) in - let* failures := (* TODO expression *) in +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 : M unit := +Definition _deserialize_to_tuple (annotation : object) (values : Simple) : M (* TODO type *) := (* TODO statement *) - let* arguments := list (| - typing.get_args (| - annotation - |) - |) in + do* M.assign "arguments" [[ + M.get_local ~(| "list" |) ~(| + typing.get_args ~(| + annotation + |) + |) in + ]] in (* TODO statement *) - let* decoded := (* TODO expression *) in + do* M.assign "decoded" [[ + (* TODO expression *) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition decode_to_bytes : M unit := +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`. @@ -234,9 +261,9 @@ Definition decode_to_bytes : M unit := RLP decoded Bytes data *) (* TODO statement *) + M.pure tt. - -Definition decode_to_sequence : M unit := +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. @@ -253,9 +280,9 @@ Definition decode_to_sequence : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition decode_joined_encodings : M unit := +Definition decode_joined_encodings (joined_encodings : Bytes) : M (* TODO type *) := (* Decodes `joined_encodings`, which is a concatenation of RLP encoded objects. @@ -270,13 +297,17 @@ Definition decode_joined_encodings : M unit := decoded : `List[RLP]` A list of objects decoded from `joined_encodings`. *) - let* decoded_sequence := (* TODO expression *) in - let* item_start_idx := (* TODO expression *) in + 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 : M unit := +Definition decode_item_length (encoded_data : Bytes) : M int := (* Find the length of the rlp encoding for the first object in the encoded sequence. @@ -297,14 +328,20 @@ Definition decode_item_length : M unit := rlp_length : `int` *) (* TODO statement *) - let* first_rlp_byte := (* TODO expression *) in - let* length_length := (* TODO expression *) in - let* decoded_data_length := (* TODO expression *) in + 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 : M unit := +Definition rlp_hash (data : Extended) : M Hash32 := (* Obtain the keccak-256 hash of the rlp encoding of the passed in data. @@ -319,4 +356,4 @@ Definition rlp_hash : M unit := The rlp hash of the passed in data. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/shanghai/__init__.v b/coq/ethereum/shanghai/__init__.v index b0649052e4..1dd362e7f8 100644 --- a/coq/ethereum/shanghai/__init__.v +++ b/coq/ethereum/shanghai/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* The Shanghai fork brings staking withdrawals to the execution layer, adds a push-zero EVM instruction, limits the maximum size of initialization diff --git a/coq/ethereum/shanghai/blocks.v b/coq/ethereum/shanghai/blocks.v index 74a6dc0d3b..110c8f0391 100644 --- a/coq/ethereum/shanghai/blocks.v +++ b/coq/ethereum/shanghai/blocks.v @@ -1,3 +1,4 @@ +(* 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 @@ -14,6 +15,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. -Require shanghai.fork_types. -Require shanghai.transactions. +Require ethereum.crypto.hash. +Require ethereum.shanghai.fork_types. +Require ethereum.shanghai.transactions. diff --git a/coq/ethereum/shanghai/bloom.v b/coq/ethereum/shanghai/bloom.v index 7652507dcd..3fe3ba02e8 100644 --- a/coq/ethereum/shanghai/bloom.v +++ b/coq/ethereum/shanghai/bloom.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Logs Bloom ^^^^^^^^^^^^^^^^^^^ @@ -19,10 +20,10 @@ eliminating blocks and receipts from their search. Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require shanghai.blocks. -Require shanghai.fork_types. +Require ethereum.shanghai.blocks. +Require ethereum.shanghai.fork_types. -Definition add_to_bloom : M unit := +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := (* Add a bloom entry to the bloom filter (`bloom`). @@ -37,13 +38,15 @@ Definition add_to_bloom : M unit := bloom_entry : An entry which is to be added to bloom filter. *) - let* hash := ethereum.crypto.hash.keccak256 (| - bloom_entry - |) in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition logs_bloom : M unit := +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := (* Obtain the logs bloom from a list of log entries. @@ -63,4 +66,4 @@ Definition logs_bloom : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/shanghai/exceptions.v b/coq/ethereum/shanghai/exceptions.v index 137ea143f6..9a313f6d0e 100644 --- a/coq/ethereum/shanghai/exceptions.v +++ b/coq/ethereum/shanghai/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Exceptions specific to this fork. *) diff --git a/coq/ethereum/shanghai/fork.v b/coq/ethereum/shanghai/fork.v index f4f3907a1a..60c0db882a 100644 --- a/coq/ethereum/shanghai/fork.v +++ b/coq/ethereum/shanghai/fork.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^ @@ -19,17 +20,19 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.exceptions. -Require shanghai.blocks. -Require shanghai.bloom. -Require shanghai.fork_types. -Require shanghai.state. -Require shanghai.transactions. -Require shanghai.trie. -Require shanghai.utils.message. -Require shanghai.vm.gas. -Require shanghai.vm.interpreter. - -Definition apply_fork : M unit := +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. @@ -49,9 +52,9 @@ Definition apply_fork : M unit := Upgraded block chain object for this hard fork. *) (* TODO statement *) + M.pure tt. - -Definition get_last_256_block_hashes : M unit := +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. @@ -71,22 +74,28 @@ Definition get_last_256_block_hashes : M unit := recent_block_hashes : `List[Hash32]` Hashes of the recent 256 blocks in order of increasing block number. *) - let* recent_blocks := (* TODO expression *) in - (* TODO statement *) - let* recent_block_hashes := (* TODO expression *) in - (* TODO statement *) - let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *).["header"] - |) - |) in - do* recent_block_hashes.["append"] (| - most_recent_block_hash - |) in - (* TODO statement *) - - -Definition state_transition : M unit := + 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. @@ -108,40 +117,44 @@ Definition state_transition : M unit := block : Block to apply to `chain`. *) - let* parent_header := (* TODO expression *).["header"] in - do* validate_header (| - block.["header"], - parent_header - |) in - (* TODO statement *) - let* apply_body_output := apply_body (| - chain.["state"], - get_last_256_block_hashes (| - chain - |), - block.["header"].["coinbase"], - block.["header"].["number"], - block.["header"].["base_fee_per_gas"], - block.["header"].["gas_limit"], - block.["header"].["timestamp"], - block.["header"].["prev_randao"], - block.["transactions"], - chain.["chain_id"], - block.["withdrawals"] - |) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - do* chain.["blocks"].["append"] (| + 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 + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_base_fee_per_gas : M unit := +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. @@ -161,13 +174,15 @@ Definition calculate_base_fee_per_gas : M unit := base_fee_per_gas : `Uint` Base fee per gas for the block. *) - let* parent_gas_target := (* TODO expression *) in + do* M.assign "parent_gas_target" [[ + (* TODO expression *) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition validate_header : M unit := +Definition validate_header (header : Header) (parent_header : Header) : M unit := (* Verifies a block header. @@ -186,12 +201,14 @@ Definition validate_header : M unit := Parent Header of the header to check for correctness *) (* TODO statement *) - let* expected_base_fee_per_gas := calculate_base_fee_per_gas (| - header.["gas_limit"], - parent_header.["gas_limit"], - parent_header.["gas_used"], - parent_header.["base_fee_per_gas"] - |) in + 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 *) @@ -199,15 +216,17 @@ Definition validate_header : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* block_parent_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - parent_header - |) - |) in + 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 : M unit := +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. @@ -235,15 +254,17 @@ Definition check_transaction : M unit := If the transaction is not includable. *) (* TODO statement *) - let* sender_address := recover_sender (| - chain_id, - tx - |) in + 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 : M unit := +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. @@ -264,13 +285,15 @@ Definition make_receipt : M unit := receipt : The receipt for the transaction. *) - let* receipt := blocks.Receipt (| + do* M.assign "receipt" [[ + blocks.Receipt ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition apply_body : M unit := +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. @@ -315,21 +338,27 @@ Definition apply_body : M unit := apply_body_output : `ApplyBodyOutput` Output of applying the block body to the state. *) - let* gas_available := block_gas_limit in + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* block_gas_used := (* TODO expression *) in - let* block_logs_bloom := bloom.logs_bloom (| - block_logs - |) 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 *) (* TODO statement *) + M.pure tt. - -Definition process_transaction : M unit := +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := (* Execute a transaction against the provided environment. @@ -357,76 +386,110 @@ Definition process_transaction : M unit := Logs generated during execution. *) (* TODO statement *) - let* sender := env.["origin"] in - let* sender_account := state.get_account (| - env.["state"], - sender - |) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* effective_gas_fee := (* TODO expression *) in - let* gas := (* TODO expression *) in - do* state.increment_nonce (| - env.["state"], - sender - |) in - let* sender_balance_after_gas_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - ethereum_types.numeric.U256 (| - sender_balance_after_gas_fee - |) - |) in - let* preaccessed_addresses := set (| - - |) in - let* preaccessed_storage_keys := set (| - - |) in - do* preaccessed_addresses.["add"] (| - env.["coinbase"] - |) in - (* TODO statement *) - let* message := utils.message.prepare_message (| - sender, - tx.["to"], - tx.["value"], - tx.["data"], - gas, - env - |) in - let* output := vm.interpreter.process_message_call (| - message, - env - |) in - let* gas_used := (* TODO expression *) in - let* gas_refund := min (| - (* TODO expression *), - ethereum_types.numeric.Uint (| - output.["refund_counter"] + 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 - let* gas_refund_amount := (* TODO expression *) in - let* priority_fee_per_gas := (* TODO expression *) in - let* transaction_fee := (* TODO expression *) in - let* total_gas_used := (* TODO expression *) in - let* sender_balance_after_refund := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - sender_balance_after_refund - |) in - let* coinbase_balance_after_mining_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - - -Definition validate_transaction : M unit := + |) ]] 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. @@ -455,9 +518,9 @@ Definition validate_transaction : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition calculate_intrinsic_cost : M unit := +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := (* Calculates the gas that is charged before execution is started. @@ -480,15 +543,19 @@ Definition calculate_intrinsic_cost : M unit := verified : `ethereum.base_types.Uint` The intrinsic cost of the transaction. *) - let* data_cost := (* TODO expression *) in + do* M.assign "data_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) - let* access_list_cost := (* TODO expression *) in + do* M.assign "access_list_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition recover_sender : M unit := +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := (* Extracts the sender address from a transaction. @@ -515,9 +582,9 @@ Definition recover_sender : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_pre155 : M unit := +Definition signing_hash_pre155 (tx : LegacyTransaction) : M Hash32 := (* Compute the hash of a transaction used in a legacy (pre EIP 155) signature. @@ -532,9 +599,9 @@ Definition signing_hash_pre155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_155 : M unit := +Definition signing_hash_155 (tx : LegacyTransaction) (chain_id : U64) : M Hash32 := (* Compute the hash of a transaction used in a EIP 155 signature. @@ -551,9 +618,9 @@ Definition signing_hash_155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_2930 : M unit := +Definition signing_hash_2930 (tx : AccessListTransaction) : M Hash32 := (* Compute the hash of a transaction used in a EIP 2930 signature. @@ -568,9 +635,9 @@ Definition signing_hash_2930 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_1559 : M unit := +Definition signing_hash_1559 (tx : FeeMarketTransaction) : M Hash32 := (* Compute the hash of a transaction used in a EIP 1559 signature. @@ -585,9 +652,9 @@ Definition signing_hash_1559 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition compute_header_hash : M unit := +Definition compute_header_hash (header : Header) : M Hash32 := (* Computes the hash of a block header. @@ -620,9 +687,9 @@ Definition compute_header_hash : M unit := Hash of the header. *) (* TODO statement *) + M.pure tt. - -Definition check_gas_limit : M unit := +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := (* Validates the gas limit for a block. @@ -650,9 +717,11 @@ Definition check_gas_limit : M unit := check : `bool` True if gas limit constraints are satisfied, False otherwise. *) - let* max_adjustment_delta := (* TODO expression *) in + 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.v b/coq/ethereum/shanghai/fork_types.v index 14de99d5e5..d84cffdf45 100644 --- a/coq/ethereum/shanghai/fork_types.v +++ b/coq/ethereum/shanghai/fork_types.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Types ^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. +Require ethereum.__init__. +Require ethereum.crypto.hash. -Definition encode_account : M unit := +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := (* Encode `Account` dataclass. @@ -26,4 +28,4 @@ Definition encode_account : M unit := encoded without providing a storage root. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/shanghai/state.v b/coq/ethereum/shanghai/state.v index 2071b465c6..05d78ff05f 100644 --- a/coq/ethereum/shanghai/state.v +++ b/coq/ethereum/shanghai/state.v @@ -1,3 +1,4 @@ +(* Generated *) (* State ^^^^^ @@ -22,11 +23,11 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require shanghai.blocks. -Require shanghai.fork_types. -Require shanghai.trie. +Require ethereum.shanghai.blocks. +Require ethereum.shanghai.fork_types. +Require ethereum.shanghai.trie. -Definition close_state : M unit := +Definition close_state (state : State) : M unit := (* Free resources held by the state. Used by optimized implementations to release file descriptors. @@ -35,9 +36,9 @@ Definition close_state : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition begin_transaction : M unit := +Definition begin_transaction (state : State) : M unit := (* Start a state transaction. @@ -49,12 +50,12 @@ Definition begin_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition commit_transaction : M unit := +Definition commit_transaction (state : State) : M unit := (* Commit a state transaction. @@ -63,13 +64,13 @@ Definition commit_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["pop"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition rollback_transaction : M unit := +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. @@ -81,9 +82,9 @@ Definition rollback_transaction : M unit := *) (* TODO assignment *) (* TODO statement *) + M.pure tt. - -Definition get_account : M unit := +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. @@ -103,14 +104,16 @@ Definition get_account : M unit := account : `Account` Account at address. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition get_account_optional : M unit := +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. @@ -127,14 +130,16 @@ Definition get_account_optional : M unit := account : `Account` Account at address. *) - let* account := trie.trie_get (| - state.["_main_trie"], - address - |) in + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition set_account : M unit := +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()`). @@ -148,14 +153,14 @@ Definition set_account : M unit := account : `Account` Account to set at address. *) - do* trie.trie_set (| - state.["_main_trie"], + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), address, account - |) in + |) ]] in + M.pure tt. - -Definition destroy_account : M unit := +Definition destroy_account (state : State) (address : Address) : M unit := (* Completely remove the account at `address` and all of its storage. @@ -170,18 +175,18 @@ Definition destroy_account : M unit := address : `Address` Address of account to destroy. *) - do* destroy_storage (| + do* [[ M.get_local ~(| "destroy_storage" |) ~(| state, address - |) in - do* set_account (| + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - (* TODO expression *) - |) in + tt + |) ]] in + M.pure tt. - -Definition destroy_storage : M unit := +Definition destroy_storage (state : State) (address : Address) : M unit := (* Completely remove the storage at `address`. @@ -193,9 +198,9 @@ Definition destroy_storage : M unit := Address of account whose storage is to be deleted. *) (* TODO statement *) + M.pure tt. - -Definition mark_account_created : M unit := +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 @@ -212,12 +217,12 @@ Definition mark_account_created : M unit := address : `Address` Address of the account that has been created. *) - do* state.["created_accounts"].["add"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| address - |) in - + |) ]] in + M.pure tt. -Definition get_storage : M unit := +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. @@ -236,19 +241,23 @@ Definition get_storage : M unit := value : `U256` Value at the key. *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition set_storage : M unit := +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. @@ -265,19 +274,21 @@ Definition set_storage : M unit := Value to set at the key. *) (* TODO statement *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - do* trie.trie_set (| - trie, + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), key, value - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition storage_root : M unit := +Definition storage_root (state : State) (address : Address) : M Root := (* Calculate the storage root of an account. @@ -295,9 +306,9 @@ Definition storage_root : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition state_root : M unit := +Definition state_root (state : State) : M Root := (* Calculate the state root. @@ -314,9 +325,9 @@ Definition state_root : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition account_exists : M unit := +Definition account_exists (state : State) (address : Address) : M bool := (* Checks if an account exists in the state trie @@ -333,9 +344,9 @@ Definition account_exists : M unit := True if account exists in the state trie, False otherwise *) (* TODO statement *) + M.pure tt. - -Definition account_has_code_or_nonce : M unit := +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := (* Checks if an account has non zero nonce or non empty code @@ -352,14 +363,16 @@ Definition account_has_code_or_nonce : M unit := True if if an account has non zero nonce or non empty code, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_empty : M unit := +Definition is_account_empty (state : State) (address : Address) : M bool := (* Checks if an account has zero nonce, empty code and zero balance. @@ -376,14 +389,16 @@ Definition is_account_empty : M unit := True if if an account has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition account_exists_and_is_empty : M unit := +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. @@ -401,14 +416,16 @@ Definition account_exists_and_is_empty : M unit := True if an account exists and has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_alive : M unit := +Definition is_account_alive (state : State) (address : Address) : M bool := (* Check whether is an account is both in the state and non empty. @@ -424,61 +441,63 @@ Definition is_account_alive : M unit := is_alive : `bool` True if the account is alive. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition modify_state : M unit := +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := (* Modify an `Account` in the `State`. *) - do* set_account (| + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - ethereum_types.frozen.modify (| - get_account (| + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| state, address |), f |) - |) in - + |) ]] in + M.pure tt. -Definition move_ether : M unit := +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := (* Move funds between accounts. *) (* TODO statement *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, sender_address, - reduce_sender_balance - |) in - do* modify_state (| + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| state, recipient_address, - increase_recipient_balance - |) in - + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. -Definition process_withdrawal : M unit := +Definition process_withdrawal (state : State) (wd : Withdrawal) : M unit := (* Increase the balance of the withdrawing account. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, - wd.["address"], - increase_recipient_balance - |) in + M.get_field ~(| wd, "address" |), + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. - -Definition set_account_balance : M unit := +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := (* Sets the balance of an account. @@ -494,14 +513,14 @@ Definition set_account_balance : M unit := The amount that needs to set in balance. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - set_balance - |) in - + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. -Definition touch_account : M unit := +Definition touch_account (state : State) (address : Address) : M unit := (* Initializes an account to state. @@ -514,9 +533,9 @@ Definition touch_account : M unit := The address of the account that need to initialised. *) (* TODO statement *) + M.pure tt. - -Definition increment_nonce : M unit := +Definition increment_nonce (state : State) (address : Address) : M unit := (* Increments the nonce of an account. @@ -529,14 +548,14 @@ Definition increment_nonce : M unit := Address of the account whose nonce needs to be incremented. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_nonce - |) in - + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. -Definition set_code : M unit := +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := (* Sets Account code. @@ -552,14 +571,14 @@ Definition set_code : M unit := The bytecode that needs to be set. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - write_code - |) in - + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. -Definition get_storage_original : M unit := +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 @@ -576,10 +595,12 @@ Definition get_storage_original : M unit := *) (* TODO statement *) (* TODO assignment *) - let* original_account_trie := original_trie.["get"] (| - address - |) in + 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.v b/coq/ethereum/shanghai/transactions.v index ce1cb59b47..5546507632 100644 --- a/coq/ethereum/shanghai/transactions.v +++ b/coq/ethereum/shanghai/transactions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, @@ -9,19 +10,20 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require shanghai.exceptions. -Require shanghai.fork_types. +Require ethereum.__init__. +Require ethereum.shanghai.exceptions. +Require ethereum.shanghai.fork_types. -Definition encode_transaction : M unit := +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 : M unit := +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.v b/coq/ethereum/shanghai/trie.v index 5f0ab29642..3b45315972 100644 --- a/coq/ethereum/shanghai/trie.v +++ b/coq/ethereum/shanghai/trie.v @@ -1,3 +1,4 @@ +(* Generated *) (* State Trie ^^^^^^^^^^ @@ -14,7 +15,7 @@ The state trie is the structure responsible for storing *) -Definition encode_internal_node : M unit := +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 @@ -35,22 +36,24 @@ Definition encode_internal_node : M unit := *) (* TODO statement *) (* TODO statement *) - let* encoded := rlp.["encode"] (| - unencoded - |) in + 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 : M unit := +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 : M unit := +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. @@ -66,9 +69,9 @@ Definition copy_trie : M unit := A copy of the trie. *) (* TODO statement *) + M.pure tt. - -Definition trie_set : M unit := +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := (* Stores an item in a Merkle Trie. @@ -85,9 +88,9 @@ Definition trie_set : M unit := Node to insert at `key`. *) (* TODO statement *) + M.pure tt. - -Definition trie_get : M unit := +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := (* Gets an item from the Merkle Trie. @@ -106,17 +109,17 @@ Definition trie_get : M unit := Node at `key` in the trie. *) (* TODO statement *) + M.pure tt. - -Definition common_prefix_length : M unit := +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 : M unit := +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := (* Compresses nibble-list into a standard byte array with a flag. @@ -150,14 +153,16 @@ Definition nibble_list_to_compact : M unit := compressed : `bytearray` Compact byte array. *) - let* compact := bytearray (| + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition bytes_to_nibble_list : M unit := +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := (* Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). @@ -171,14 +176,16 @@ Definition bytes_to_nibble_list : M unit := nibble_list : `Bytes` The `Bytes` in nibble-list format. *) - let* nibble_list := bytearray (| - (* TODO expression *) - |) in + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _prepare_trie : M unit := +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. @@ -199,9 +206,9 @@ Definition _prepare_trie : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition root : M unit := +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := (* Computes the root of a modified merkle patricia trie (MPT). @@ -219,22 +226,26 @@ Definition root : M unit := root : `.fork_types.Root` MPT root of the underlying key-value pairs. *) - let* obj := _prepare_trie (| - trie, - get_storage_root - |) in - let* root_node := encode_internal_node (| - patricialize (| - obj, - Uint (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) + M.pure tt. - -Definition patricialize : M unit := +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := (* Structural composition function. @@ -254,21 +265,29 @@ Definition patricialize : M unit := Root node of `obj`. *) (* TODO statement *) - let* arbitrary_key := next (| - iter (| - obj - |) - |) in + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in (* TODO statement *) - let* substring := (* TODO expression *) in - let* prefix_length := len (| - substring - |) in + 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 *) - let* value := (* TODO expression *) in + do* M.assign "value" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/shanghai/utils/__init__.v b/coq/ethereum/shanghai/utils/__init__.v index beff4482b1..7f30fe939b 100644 --- a/coq/ethereum/shanghai/utils/__init__.v +++ b/coq/ethereum/shanghai/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions unique to this particular fork. *) diff --git a/coq/ethereum/shanghai/utils/address.v b/coq/ethereum/shanghai/utils/address.v index 1d6651723b..514852436f 100644 --- a/coq/ethereum/shanghai/utils/address.v +++ b/coq/ethereum/shanghai/utils/address.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,9 +19,10 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require shanghai.fork_types. +Require ethereum.__init__. +Require ethereum.shanghai.fork_types. -Definition to_address : M unit := +Definition to_address (data : (* TODO type *)) : M Address := (* Convert a Uint or U256 value to a valid address (20 bytes). @@ -35,9 +37,9 @@ Definition to_address : M unit := The obtained address. *) (* TODO statement *) + M.pure tt. - -Definition compute_contract_address : M unit := +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := (* Computes address of the new account that needs to be created. @@ -54,20 +56,26 @@ Definition compute_contract_address : M unit := address: `Address` The computed address of the new account. *) - let* computed_address := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *) - |) - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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 : M unit := +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. @@ -86,14 +94,22 @@ Definition compute_create2_contract_address : M unit := address: `ethereum.shanghai.fork_types.Address` The computed address of the new account. *) - let* preimage := (* TODO expression *) in - let* computed_address := ethereum.crypto.hash.keccak256 (| - preimage - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/shanghai/utils/hexadecimal.v index 74a883654f..e674290c63 100644 --- a/coq/ethereum/shanghai/utils/hexadecimal.v +++ b/coq/ethereum/shanghai/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Shanghai types. *) Require ethereum.utils.hexadecimal. -Require shanghai.fork_types. +Require ethereum.shanghai.fork_types. -Definition hex_to_root : M unit := +Definition hex_to_root (hex_string : str) : M Root := (* Convert hex string to trie root. @@ -31,9 +32,9 @@ Definition hex_to_root : M unit := Trie root obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bloom : M unit := +Definition hex_to_bloom (hex_string : str) : M Bloom := (* Convert hex string to bloom. @@ -48,9 +49,9 @@ Definition hex_to_bloom : M unit := Bloom obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_address : M unit := +Definition hex_to_address (hex_string : str) : M Address := (* Convert hex string to Address (20 bytes). @@ -65,4 +66,4 @@ Definition hex_to_address : M unit := The address obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/shanghai/utils/message.v b/coq/ethereum/shanghai/utils/message.v index 03aff15c2f..f35544420d 100644 --- a/coq/ethereum/shanghai/utils/message.v +++ b/coq/ethereum/shanghai/utils/message.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For The Message Data-structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,13 +17,13 @@ specification. Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require shanghai.fork_types. -Require shanghai.state. -Require shanghai.vm. -Require shanghai.vm.precompiled_contracts.mapping. -Require shanghai.utils.address. +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 : M unit := +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. @@ -61,22 +62,24 @@ Definition prepare_message : M unit := Items containing contract creation or message call specific data. *) (* TODO statement *) - let* accessed_addresses := set (| + do* M.assign "accessed_addresses" [[ + M.get_local ~(| "set" |) ~(| - |) in - do* accessed_addresses.["add"] (| - current_target - |) in - do* accessed_addresses.["add"] (| + |) 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* accessed_addresses.["update"] (| - vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS.["keys"] (| + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS, "keys" |) ~(| |) - |) in - do* accessed_addresses.["update"] (| + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| preaccessed_addresses - |) in + |) ]] in (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/__init__.v b/coq/ethereum/shanghai/vm/__init__.v index 20d5165e4f..191af3aebd 100644 --- a/coq/ethereum/shanghai/vm/__init__.v +++ b/coq/ethereum/shanghai/vm/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,12 +19,12 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require shanghai.blocks. -Require shanghai.fork_types. -Require shanghai.state. -Require shanghai.vm.precompiled_contracts. +Require ethereum.shanghai.blocks. +Require ethereum.shanghai.fork_types. +Require ethereum.shanghai.state. +Require ethereum.shanghai.vm.precompiled_contracts. -Definition incorporate_child_on_success : M unit := +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of a successful `child_evm` into the parent `evm`. @@ -34,25 +35,31 @@ Definition incorporate_child_on_success : M unit := 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 *) - (* TODO statement *) - (* TODO statement *) - do* evm.["accounts_to_delete"].["update"] (| - child_evm.["accounts_to_delete"] - |) in - do* evm.["touched_accounts"].["update"] (| - child_evm.["touched_accounts"] - |) in - (* TODO statement *) - do* evm.["accessed_addresses"].["update"] (| - child_evm.["accessed_addresses"] - |) in - do* evm.["accessed_storage_keys"].["update"] (| - child_evm.["accessed_storage_keys"] - |) in + 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 : M unit := +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. @@ -65,5 +72,7 @@ Definition incorporate_child_on_error : M unit := *) (* TODO statement *) (* 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.v b/coq/ethereum/shanghai/vm/exceptions.v index 1784494410..47e26555d5 100644 --- a/coq/ethereum/shanghai/vm/exceptions.v +++ b/coq/ethereum/shanghai/vm/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Exceptions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/shanghai/vm/gas.v b/coq/ethereum/shanghai/vm/gas.v index 6e166e3091..de3d208eed 100644 --- a/coq/ethereum/shanghai/vm/gas.v +++ b/coq/ethereum/shanghai/vm/gas.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Gas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,9 +18,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.trace. Require ethereum.utils.numeric. -Require shanghai.vm.exceptions. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.exceptions. -Definition charge_gas : M unit := +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := (* Subtracts `amount` from `evm.gas_left`. @@ -31,18 +33,18 @@ Definition charge_gas : M unit := The amount of gas the current operation requires. *) - do* ethereum.trace.evm_trace (| + do* [[ ethereum.trace.evm_trace ~(| evm, - ethereum.trace.GasAndRefund (| - int (| + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| amount |) |) - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_memory_gas_cost : M unit := +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, @@ -58,14 +60,22 @@ Definition calculate_memory_gas_cost : M unit := total_gas_cost : `ethereum.base_types.Uint` The gas cost for storing data in memory. *) - let* size_in_words := (* TODO expression *) in - let* linear_cost := (* TODO expression *) in - let* quadratic_cost := (* TODO expression *) in - let* total_gas_cost := (* TODO expression *) in + 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 : M unit := +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := (* Calculates the gas amount to extend memory @@ -81,22 +91,28 @@ Definition calculate_gas_extend_memory : M unit := ------- extend_memory: `ExtendMemory` *) - let* size_to_extend := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* to_be_paid := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* current_size := ethereum_types.numeric.Uint (| - len (| - memory - |) - |) in + 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 : M unit := +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. @@ -122,18 +138,22 @@ Definition calculate_message_call_gas : M unit := ------- message_call_gas: `MessageCallGas` *) - let* call_stipend := (* TODO expression *) in + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* gas := min (| - gas, - max_message_call_gas (| - (* TODO expression *) - |) - |) in + 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 : M unit := +Definition max_message_call_gas (gas : Uint) : M Uint := (* Calculates the maximum gas that is allowed for making a message call @@ -148,9 +168,9 @@ Definition max_message_call_gas : M unit := The maximum gas allowed for making the message-call. *) (* TODO statement *) + M.pure tt. - -Definition init_code_cost : M unit := +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. @@ -167,4 +187,4 @@ Definition init_code_cost : M unit := The gas to be charged for the init code. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/instructions/__init__.v b/coq/ethereum/shanghai/vm/instructions/__init__.v index b36b1ebfef..cbd7e7e63a 100644 --- a/coq/ethereum/shanghai/vm/instructions/__init__.v +++ b/coq/ethereum/shanghai/vm/instructions/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* EVM Instruction Encoding (Opcodes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/shanghai/vm/instructions/arithmetic.v b/coq/ethereum/shanghai/vm/instructions/arithmetic.v index a41f76b70d..bf74628847 100644 --- a/coq/ethereum/shanghai/vm/instructions/arithmetic.v +++ b/coq/ethereum/shanghai/vm/instructions/arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,11 @@ Implementations of the EVM Arithmetic instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require shanghai.vm.gas. -Require shanghai.vm.stack. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.stack. -Definition add : M unit := +Definition add (evm : Evm) : M unit := (* Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -28,27 +30,37 @@ Definition add : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_add"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sub (evm : Evm) : M unit := (* Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -59,27 +71,37 @@ Definition sub : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_sub"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mul (evm : Evm) : M unit := (* Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -90,27 +112,37 @@ Definition mul : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_mul"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition div (evm : Evm) : M unit := (* Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -121,25 +153,33 @@ Definition div : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |) in - let* divisor := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - quotient - |) 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 : M unit := +Definition sdiv (evm : Evm) : M unit := (* Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -150,31 +190,39 @@ Definition sdiv : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* divisor := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - quotient + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mod : M unit := +Definition mod (evm : Evm) : M unit := (* Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -185,25 +233,33 @@ Definition mod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - remainder - |) in + |) ]] 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 : M unit := +Definition smod (evm : Evm) : M unit := (* Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -214,31 +270,39 @@ Definition smod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* y := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - remainder + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition addmod : M unit := +Definition addmod (evm : Evm) : M unit := (* Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -249,34 +313,44 @@ Definition addmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +Definition mulmod (evm : Evm) : M unit := (* Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -287,34 +361,44 @@ Definition mulmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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 : M unit := +Definition exp (evm : Evm) : M unit := (* Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -325,39 +409,53 @@ Definition exp : M unit := The current EVM frame. *) - let* base := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent_bits := exponent.["bit_length"] (| - - |) in - let* exponent_bytes := (* TODO expression *) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - pow (| - base, - exponent, - (* 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 - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition signextend : M unit := +Definition signextend (evm : Evm) : M unit := (* Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -368,20 +466,28 @@ Definition signextend : M unit := The current EVM frame. *) - let* byte_num := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/shanghai/vm/instructions/bitwise.v index 29ee35e562..d2e1b28c76 100644 --- a/coq/ethereum/shanghai/vm/instructions/bitwise.v +++ b/coq/ethereum/shanghai/vm/instructions/bitwise.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Bitwise Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM bitwise instructions. *) Require ethereum_types.numeric. -Require shanghai.vm.gas. -Require shanghai.vm.stack. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.stack. -Definition bitwise_and : M unit := +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. @@ -27,24 +29,32 @@ Definition bitwise_and : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_or : M unit := +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. @@ -55,24 +65,32 @@ Definition bitwise_or : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_xor : M unit := +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. @@ -83,24 +101,32 @@ Definition bitwise_xor : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition bitwise_not : M unit := +Definition bitwise_not (evm : Evm) : M unit := (* Bitwise NOT operation of the top element of the stack. Pushes the result back on the stack. @@ -111,21 +137,27 @@ Definition bitwise_not : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition get_byte : M unit := +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 @@ -137,25 +169,33 @@ Definition get_byte : M unit := The current EVM frame. *) - let* byte_index := stack.pop (| - evm.["stack"] - |) in - let* word := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -164,29 +204,37 @@ Definition bitwise_shl : M unit := evm : The current EVM frame. *) - let* shift := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -195,25 +243,33 @@ Definition bitwise_shr : M unit := evm : The current EVM frame. *) - let* shift := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +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. @@ -222,24 +278,32 @@ Definition bitwise_sar : M unit := evm : The current EVM frame. *) - let* shift := int (| - stack.pop (| - evm.["stack"] - |) - |) in - let* signed_value := stack.pop (| - evm.["stack"] - |).["to_signed"] (| + 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 - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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.v b/coq/ethereum/shanghai/vm/instructions/block.v index f4a5ae1d9e..c843334534 100644 --- a/coq/ethereum/shanghai/vm/instructions/block.v +++ b/coq/ethereum/shanghai/vm/instructions/block.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Block Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM block instructions. *) Require ethereum_types.numeric. -Require shanghai.vm.gas. -Require shanghai.vm.stack. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.stack. -Definition block_hash : M unit := +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. @@ -33,27 +35,35 @@ Definition block_hash : M unit := :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError` If `evm.gas_left` is less than `20`. *) - let* block_number := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* max_block_number := (* TODO expression *) in + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition coinbase : M unit := +Definition coinbase (evm : Evm) : M unit := (* Push the current block's beneficiary address (address of the block miner) onto the stack. @@ -74,20 +84,24 @@ Definition coinbase : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["coinbase"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition timestamp : M unit := +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. @@ -108,18 +122,22 @@ Definition timestamp : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["env"].["time"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition number (evm : Evm) : M unit := (* Push the current block's number onto the stack. @@ -139,20 +157,24 @@ Definition number : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["number"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition prev_randao : M unit := +Definition prev_randao (evm : Evm) : M unit := (* Push the `prev_randao` value onto the stack. @@ -172,20 +194,24 @@ Definition prev_randao : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["prev_randao"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_limit : M unit := +Definition gas_limit (evm : Evm) : M unit := (* Push the current block's gas limit onto the stack. @@ -205,20 +231,24 @@ Definition gas_limit : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_limit"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition chain_id : M unit := +Definition chain_id (evm : Evm) : M unit := (* Push the chain id onto the stack. @@ -235,15 +265,19 @@ Definition chain_id : M unit := If `evm.gas_left` is less than `2`. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["chain_id"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/shanghai/vm/instructions/comparison.v index 3c0796c850..c0e9153fec 100644 --- a/coq/ethereum/shanghai/vm/instructions/comparison.v +++ b/coq/ethereum/shanghai/vm/instructions/comparison.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Comparison Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM Comparison instructions. *) Require ethereum_types.numeric. -Require shanghai.vm.gas. -Require shanghai.vm.stack. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.stack. -Definition less_than : M unit := +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. @@ -27,27 +29,37 @@ Definition less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_less_than : M unit := + |) ]] 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. @@ -57,31 +69,41 @@ Definition signed_less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition greater_than : M unit := + |) ]] 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. @@ -92,27 +114,37 @@ Definition greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_greater_than : M unit := + |) ]] 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. @@ -122,31 +154,41 @@ Definition signed_greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition equal : M unit := + |) ]] 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. @@ -157,27 +199,37 @@ Definition equal : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition is_zero : M unit := + |) ]] 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. @@ -188,19 +240,27 @@ Definition is_zero : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/shanghai/vm/instructions/control_flow.v index d9f8f0e32d..a6aab3d2bd 100644 --- a/coq/ethereum/shanghai/vm/instructions/control_flow.v +++ b/coq/ethereum/shanghai/vm/instructions/control_flow.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Control Flow Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM control flow instructions. *) Require ethereum_types.numeric. -Require shanghai.vm.gas. -Require shanghai.vm.exceptions. -Require shanghai.vm.stack. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.exceptions. +Require ethereum.shanghai.vm.stack. -Definition stop : M unit := +Definition stop (evm : Evm) : M unit := (* Stop further execution of EVM code. @@ -29,10 +31,14 @@ Definition stop : M unit := (* TODO statement *) (* TODO statement *) (* TODO assignment *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jump : M unit := +Definition jump (evm : Evm) : M unit := (* Alter the program counter to the location specified by the top of the stack. @@ -43,20 +49,22 @@ Definition jump : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition jumpi : M unit := +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 @@ -68,23 +76,27 @@ Definition jumpi : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* conditional_value := stack.pop (| - evm.["stack"] - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition pc : M unit := +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. @@ -96,20 +108,24 @@ Definition pc : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["pc"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_left : M unit := +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. @@ -121,20 +137,24 @@ Definition gas_left : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["gas_left"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jumpdest : M unit := +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 @@ -147,10 +167,14 @@ Definition jumpdest : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_JUMPDEST - |) in - (* TODO statement *) + |) ]] 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.v b/coq/ethereum/shanghai/vm/instructions/environment.v index 08e53d2f4b..2edf834c61 100644 --- a/coq/ethereum/shanghai/vm/instructions/environment.v +++ b/coq/ethereum/shanghai/vm/instructions/environment.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,15 +16,16 @@ Implementations of the EVM environment related instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require shanghai.fork_types. -Require shanghai.state. -Require shanghai.utils.address. -Require shanghai.vm.memory. -Require shanghai.vm.exceptions. -Require shanghai.vm.gas. -Require shanghai.vm.stack. - -Definition address : M unit := +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. @@ -34,20 +36,24 @@ Definition address : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["current_target"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition balance : M unit := +Definition balance (evm : Evm) : M unit := (* Pushes the balance of the given account onto the stack. @@ -57,24 +63,32 @@ Definition balance : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] + 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 - (* TODO statement *) - let* balance := state.get_account (| - evm.["env"].["state"], - address - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition origin : M unit := +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. @@ -86,20 +100,24 @@ Definition origin : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["origin"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition caller : M unit := +Definition caller (evm : Evm) : M unit := (* Pushes the address of the caller onto the stack. @@ -110,20 +128,24 @@ Definition caller : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["caller"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition callvalue : M unit := +Definition callvalue (evm : Evm) : M unit := (* Push the value (in wei) sent with the call onto the stack. @@ -134,18 +156,22 @@ Definition callvalue : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["message"].["value"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition calldataload (evm : Evm) : M unit := (* Push a word (32 bytes) of the input data belonging to the current environment onto the stack. @@ -156,30 +182,38 @@ Definition calldataload : M unit := The current EVM frame. *) - let* start_index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - start_index, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] 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* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - value + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 |) - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition calldatasize : M unit := +Definition calldatasize (evm : Evm) : M unit := (* Push the size of input data in current environment onto the stack. @@ -190,22 +224,26 @@ Definition calldatasize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["message"].["data"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition calldatacopy : M unit := +Definition calldatacopy (evm : Evm) : M unit := (* Copy a portion of the input data in current environment to memory. @@ -218,40 +256,60 @@ Definition calldatacopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* data_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - data_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition codesize (evm : Evm) : M unit := (* Push the size of code running in current environment onto the stack. @@ -262,22 +320,26 @@ Definition codesize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["code"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition codecopy : M unit := +Definition codecopy (evm : Evm) : M unit := (* Copy a portion of the code in current environment to memory. @@ -290,40 +352,60 @@ Definition codecopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["code"], - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition gasprice (evm : Evm) : M unit := (* Push the gas price used in current environment onto the stack. @@ -334,20 +416,24 @@ Definition gasprice : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_price"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition extcodesize : M unit := +Definition extcodesize (evm : Evm) : M unit := (* Push the code size of a given account onto the stack. @@ -357,28 +443,36 @@ Definition extcodesize : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - (* TODO statement *) - let* codesize := ethereum_types.numeric.U256 (| - len (| - state.get_account (| - evm.["env"].["state"], - address - |).["code"] + 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 - do* stack.push (| - evm.["stack"], - codesize - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition extcodecopy : M unit := +Definition extcodecopy (evm : Evm) : M unit := (* Copy a portion of an account's code to memory. @@ -388,46 +482,70 @@ Definition extcodecopy : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - (* TODO statement *) - let* code := state.get_account (| - evm.["env"].["state"], - address - |).["code"] in - let* value := vm.memory.buffer_read (| - code, - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in + 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 : M unit := +Definition returndatasize (evm : Evm) : M unit := (* Pushes the size of the return data buffer onto the stack. @@ -437,22 +555,26 @@ Definition returndatasize : M unit := The current EVM frame. *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["return_data"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition returndatacopy : M unit := +Definition returndatacopy (evm : Evm) : M unit := (* Copies data from the return data buffer code to memory @@ -461,37 +583,57 @@ Definition returndatacopy : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* return_data_start_position := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - (* TODO statement *) - let* value := (* TODO expression *) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in + |) ]] 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 : M unit := +Definition extcodehash (evm : Evm) : M unit := (* Returns the keccak256 hash of a contract’s bytecode Parameters @@ -499,25 +641,33 @@ Definition extcodehash : M unit := evm : The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] + 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 - (* TODO statement *) - let* account := state.get_account (| - evm.["env"].["state"], - address - |) in - (* TODO statement *) - do* stack.push (| - evm.["stack"], - codehash - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition self_balance : M unit := +Definition self_balance (evm : Evm) : M unit := (* Pushes the balance of the current address to the stack. @@ -528,22 +678,28 @@ Definition self_balance : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_FAST_STEP - |) in - let* balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition base_fee (evm : Evm) : M unit := (* Pushes the base fee of the current block on to the stack. @@ -554,15 +710,19 @@ Definition base_fee : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["base_fee_per_gas"] + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/shanghai/vm/instructions/keccak.v index 47aeac27c2..fa3a063222 100644 --- a/coq/ethereum/shanghai/vm/instructions/keccak.v +++ b/coq/ethereum/shanghai/vm/instructions/keccak.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Keccak Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM keccak instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require shanghai.vm.gas. -Require shanghai.vm.memory. -Require shanghai.vm.stack. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.memory. +Require ethereum.shanghai.vm.stack. -Definition keccak : M unit := +Definition keccak (evm : Evm) : M unit := (* Pushes to the stack the Keccak-256 hash of a region of memory. @@ -32,36 +34,56 @@ Definition keccak : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* word_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in - let* hash := ethereum.crypto.hash.keccak256 (| - data - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/shanghai/vm/instructions/log.v index 4fff4c4261..a66b3318e5 100644 --- a/coq/ethereum/shanghai/vm/instructions/log.v +++ b/coq/ethereum/shanghai/vm/instructions/log.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Logging Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,13 +15,14 @@ Implementations of the EVM logging instructions. Require functools. Require ethereum_types.numeric. -Require shanghai.blocks. -Require shanghai.vm.exceptions. -Require shanghai.vm.gas. -Require shanghai.vm.memory. -Require shanghai.vm.stack. +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 : M unit := +Definition log_n (evm : Evm) (num_topics : U256) : M unit := (* Appends a log entry, having `num_topics` topics, to the evm logs. @@ -35,27 +37,43 @@ Definition log_n : M unit := The number of topics to be included in the log entry. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* topics := (* TODO expression *) in + 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 *) - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in (* TODO statement *) - let* log_entry := blocks.Log (| + do* M.assign "log_entry" [[ + blocks.Log ~(| - |) in + |) in + ]] in (* TODO assignment *) - (* 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/memory.v b/coq/ethereum/shanghai/vm/instructions/memory.v index bec982f2ff..2ae905686e 100644 --- a/coq/ethereum/shanghai/vm/instructions/memory.v +++ b/coq/ethereum/shanghai/vm/instructions/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM Memory instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require shanghai.vm.gas. -Require shanghai.vm.memory. -Require shanghai.vm.stack. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.memory. +Require ethereum.shanghai.vm.stack. -Definition mstore : M unit := +Definition mstore (evm : Evm) : M unit := (* Stores a word to memory. This also expands the memory, if the memory is @@ -30,32 +32,44 @@ Definition mstore : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* memory.memory_write (| - evm.["memory"], - start_position, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mstore8 (evm : Evm) : M unit := (* Stores a byte to memory. This also expands the memory, if the memory is @@ -67,33 +81,47 @@ Definition mstore8 : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ (* TODO expression *) - |) in - do* memory.memory_write (| - evm.["memory"], - start_position, - normalized_bytes_value - |) in - (* TODO statement *) - + ]] 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 : M unit := +Definition mload (evm : Evm) : M unit := (* Load word from memory. @@ -103,35 +131,47 @@ Definition mload : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.memory_read_bytes (| - evm.["memory"], - start_position, - ethereum_types.numeric.U256 (| - (* 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 - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition msize : M unit := +Definition msize (evm : Evm) : M unit := (* Push the size of active memory in bytes onto the stack. @@ -142,17 +182,21 @@ Definition msize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["memory"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/shanghai/vm/instructions/stack.v index 24ccc6f94b..ed16cd5863 100644 --- a/coq/ethereum/shanghai/vm/instructions/stack.v +++ b/coq/ethereum/shanghai/vm/instructions/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM stack related instructions. Require functools. Require ethereum_types.numeric. -Require shanghai.vm.exceptions. -Require shanghai.vm.gas. -Require shanghai.vm.memory. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.exceptions. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.memory. -Definition pop : M unit := +Definition pop (evm : Evm) : M unit := (* Remove item from stack. @@ -28,18 +30,22 @@ Definition pop : M unit := The current EVM frame. *) - do* stack.["pop"] (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in + |) ]] in (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition push_n : M unit := +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. @@ -55,25 +61,29 @@ Definition push_n : M unit := *) (* TODO statement *) (* TODO statement *) - let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - evm.["code"], - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - num_bytes + 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 - do* stack.["push"] (| - evm.["stack"], - data_to_push - |) in - (* TODO statement *) - - -Definition dup_n : M unit := + |) 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. @@ -88,20 +98,26 @@ Definition dup_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - let* data_to_duplicate := (* TODO expression *) in - do* stack.["push"] (| - evm.["stack"], - data_to_duplicate - |) 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 : M unit := +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. @@ -120,11 +136,15 @@ Definition swap_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - (* 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/storage.v b/coq/ethereum/shanghai/vm/instructions/storage.v index e65584a478..b17f648ba0 100644 --- a/coq/ethereum/shanghai/vm/instructions/storage.v +++ b/coq/ethereum/shanghai/vm/instructions/storage.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Storage Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,12 +14,13 @@ Implementations of the EVM storage related instructions. *) Require ethereum_types.numeric. -Require shanghai.state. -Require shanghai.vm.exceptions. -Require shanghai.vm.gas. -Require shanghai.vm.stack. +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 : M unit := +Definition sload (evm : Evm) : M unit := (* Loads to the stack, the value corresponding to a certain key from the storage of the current account. @@ -29,25 +31,33 @@ Definition sload : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in + |) in + ]] in (* TODO statement *) - let* value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) 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 : M unit := +Definition sstore (evm : Evm) : M unit := (* Stores a value at a certain key in the current context's storage. @@ -57,41 +67,55 @@ Definition sstore : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in (* TODO statement *) - let* original_value := state.get_storage_original (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - let* current_value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - let* gas_cost := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in + M.get_local ~(| "gas_cost" |) + |) ]] in (* TODO statement *) - do* state.set_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key, - new_value - |) 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.v b/coq/ethereum/shanghai/vm/instructions/system.v index e0695c9e7e..244e30b62a 100644 --- a/coq/ethereum/shanghai/vm/instructions/system.v +++ b/coq/ethereum/shanghai/vm/instructions/system.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) System Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,58 +16,73 @@ Implementations of the EVM system related instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require shanghai.fork_types. -Require shanghai.state. -Require shanghai.utils.address. -Require shanghai.vm.exceptions. -Require shanghai.vm.gas. -Require shanghai.vm.memory. -Require shanghai.vm.stack. - -Definition generic_create : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) in + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_start_position, + memory_size + |) in + ]] in (* TODO statement *) - do* evm.["accessed_addresses"].["add"] (| + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "add" |) ~(| contract_address - |) in - let* create_message_gas := gas.max_message_call_gas (| - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |) - |) in - (* TODO statement *) + |) ]] 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 *) - let* sender_address := evm.["message"].["current_target"] in - let* sender := state.get_account (| - evm.["env"].["state"], - sender_address - |) in - (* TODO statement *) - (* TODO statement *) - do* state.increment_nonce (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |) in - let* child_message := Message (| - - |) in - let* child_evm := process_create_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - - -Definition create : M unit := + 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. @@ -75,48 +91,66 @@ Definition create : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* init_code_gas := gas.init_code_cost (| - ethereum_types.numeric.Uint (| - memory_size - |) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_contract_address (| - evm.["message"].["current_target"], - state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["nonce"] - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size, - init_code_gas - |) in - (* TODO statement *) - + 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 : M unit := +Definition create2 (evm : Evm) : M unit := (* Creates a new account with associated code. @@ -128,56 +162,78 @@ Definition create2 : M unit := evm : The current EVM frame. *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* salt := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* call_data_words := (* TODO expression *) in - let* init_code_gas := gas.init_code_cost (| - ethereum_types.numeric.Uint (| - memory_size - |) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* contract_address := utils.address.compute_create2_contract_address (| - evm.["message"].["current_target"], - salt, - memory.memory_read_bytes (| - evm.["memory"], - memory_start_position, - memory_size - |) - |) in - do* generic_create (| + |) ]] 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, - endowment, - contract_address, - memory_start_position, - memory_size, - init_code_gas - |) in - (* TODO statement *) - + 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_ : M unit := +Definition return_ (evm : Evm) : M unit := (* Halts execution returning output data. @@ -186,66 +242,84 @@ Definition return_ : M unit := evm : The current EVM frame. *) - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) + |) ]] 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 : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_input_start_position, - memory_input_size - |) in - let* code := state.get_account (| - evm.["env"].["state"], - code_address - |).["code"] in - let* child_message := Message (| - - |) in - let* child_evm := process_message (| - child_message, - evm.["env"] - |) in - (* TODO statement *) - let* actual_output_size := min (| - memory_output_size, - ethereum_types.numeric.U256 (| - len (| - child_evm.["output"] + 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 - do* memory.memory_write (| - evm.["memory"], + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), memory_output_start_position, (* TODO expression *) - |) in + |) ]] in + M.pure tt. - -Definition call : M unit := +Definition call (evm : Evm) : M unit := (* Message-call into an account. @@ -254,62 +328,92 @@ Definition call : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* create_gas_cost := (* TODO expression *) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition callcode (evm : Evm) : M unit := (* Message-call into this account with alternative account’s code. @@ -318,61 +422,91 @@ Definition callcode : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* to := evm.["message"].["current_target"] in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) - (* TODO statement *) - + |) ]] 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 : M unit := +Definition selfdestruct (evm : Evm) : M unit := (* Halt execution and register account for later deletion. @@ -381,49 +515,59 @@ Definition selfdestruct : M unit := evm : The current EVM frame. *) - let* beneficiary := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* gas_cost := gas.GAS_SELF_DESTRUCT in + 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - (* TODO statement *) - let* originator := evm.["message"].["current_target"] in - let* beneficiary_balance := state.get_account (| - evm.["env"].["state"], - beneficiary - |).["balance"] in - let* originator_balance := state.get_account (| - evm.["env"].["state"], - originator - |).["balance"] in - do* state.set_account_balance (| - evm.["env"].["state"], - beneficiary, + 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 (| - evm.["env"].["state"], - originator, - ethereum_types.numeric.U256 (| - (* 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* evm.["accounts_to_delete"].["add"] (| - originator - |) in + |) ]] 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 : M unit := +Definition delegatecall (evm : Evm) : M unit := (* Message-call into an account. @@ -432,67 +576,89 @@ Definition delegatecall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - access_gas_cost - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - evm.["message"].["value"], - evm.["message"].["caller"], - evm.["message"].["current_target"], - code_address, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +Definition staticcall (evm : Evm) : M unit := (* Message-call into an account. @@ -501,69 +667,91 @@ Definition staticcall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - (* TODO statement *) - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - access_gas_cost - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - ethereum_types.numeric.U256 (| - (* TODO expression *) + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 |), - evm.["message"].["current_target"], - to, - to, - (* TODO expression *), - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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 : M unit := +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 @@ -572,27 +760,37 @@ Definition revert : M unit := evm : The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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, - extend_memory.["cost"] - |) in - (* TODO statement *) - let* output := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in + 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.v b/coq/ethereum/shanghai/vm/interpreter.v index 03268f520c..86974f46b4 100644 --- a/coq/ethereum/shanghai/vm/interpreter.v +++ b/coq/ethereum/shanghai/vm/interpreter.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Interpreter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +18,18 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.trace. -Require shanghai.blocks. -Require shanghai.fork_types. -Require shanghai.state. -Require shanghai.vm. -Require shanghai.vm.gas. -Require shanghai.vm.precompiled_contracts.mapping. -Require shanghai.vm.exceptions. -Require shanghai.vm.instructions. -Require shanghai.vm.runtime. - -Definition process_message_call : M unit := +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`. @@ -47,19 +49,21 @@ Definition process_message_call : M unit := *) (* TODO statement *) (* TODO statement *) - let* tx_end := ethereum.trace.TransactionEnd (| - (* TODO expression *), - evm.["output"], - evm.["error"] - |) in - do* ethereum.trace.evm_trace (| - evm, - tx_end - |) in + 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 : M unit := +Definition process_create_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -75,30 +79,32 @@ Definition process_create_message : M unit := evm: :py:class:`~ethereum.shanghai.vm.Evm` Items containing execution specific objects. *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.destroy_storage (| - env.["state"], - message.["current_target"] - |) in - do* state.mark_account_created (| - env.["state"], - message.["current_target"] - |) in - do* state.increment_nonce (| - env.["state"], - message.["current_target"] - |) in - let* evm := process_message (| - message, - env - |) in + 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 : M unit := +Definition process_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -115,23 +121,25 @@ Definition process_message : M unit := Items containing execution specific objects *) (* TODO statement *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.touch_account (| - env.["state"], - message.["current_target"] - |) in + 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 *) - let* evm := execute_code (| - message, - env - |) in + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition execute_code : M unit := +Definition execute_code (message : Message) (env : Environment) : M Evm := (* Executes bytecode present in the `message`. @@ -147,13 +155,19 @@ Definition execute_code : M unit := evm: `ethereum.vm.EVM` Items containing execution specific objects *) - let* code := message.["code"] in - let* valid_jump_destinations := runtime.get_valid_jump_destinations (| - code - |) in - let* evm := Evm (| - - |) in + 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.v b/coq/ethereum/shanghai/vm/memory.v index 94b6a44639..88b516318f 100644 --- a/coq/ethereum/shanghai/vm/memory.v +++ b/coq/ethereum/shanghai/vm/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.byte. -Definition memory_write : M unit := +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := (* Writes to memory. @@ -30,9 +31,9 @@ Definition memory_write : M unit := Data to write to memory. *) (* TODO assignment *) + M.pure tt. - -Definition memory_read_bytes : M unit := +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := (* Read bytes from memory. @@ -51,9 +52,9 @@ Definition memory_read_bytes : M unit := Data read from memory. *) (* TODO statement *) + M.pure tt. - -Definition buffer_read : M unit := +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := (* Read bytes from a buffer. Padding with zeros if necessary. @@ -72,4 +73,4 @@ Definition buffer_read : M unit := Data read from memory. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/__init__.v b/coq/ethereum/shanghai/vm/precompiled_contracts/__init__.v index 529f15525e..ad37fcb596 100644 --- a/coq/ethereum/shanghai/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,4 +14,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require shanghai.utils.hexadecimal. +Require ethereum.shanghai.utils.hexadecimal. diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.v index d07cfa8502..8006b0bef2 100644 --- a/coq/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.v +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,12 +15,12 @@ Implementation of the ALT_BN128 precompiled contracts. Require ethereum_types.numeric. Require ethereum.crypto.alt_bn128. -Require shanghai.vm. -Require shanghai.vm.gas. -Require shanghai.vm.memory. -Require shanghai.vm.exceptions. +Require ethereum.shanghai.vm. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.memory. +Require ethereum.shanghai.vm.exceptions. -Definition alt_bn128_add : M unit := +Definition alt_bn128_add (evm : Evm) : M unit := (* The ALT_BN128 addition precompiled contract. @@ -28,76 +29,96 @@ Definition alt_bn128_add : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* x1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x1_bytes - |) - |) in - let* y1_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y1_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y1_bytes - |) - |) in + 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 *) - let* p := (* TODO expression *) in + do* M.assign "p" [[ + (* TODO expression *) in + ]] in (* TODO assignment *) + M.pure tt. - -Definition alt_bn128_mul : M unit := +Definition alt_bn128_mul (evm : Evm) : M unit := (* The ALT_BN128 multiplication precompiled contract. @@ -106,63 +127,77 @@ Definition alt_bn128_mul : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* x0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* x0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - x0_bytes - |) - |) in - let* y0_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* y0_value := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - y0_bytes - |) - |) in - let* n := int (| - ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) (* TODO statement *) - let* p := p0.["mul_by"] (| - n - |) in + 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 : M unit := +Definition alt_bn128_pairing_check (evm : Evm) : M unit := (* The ALT_BN128 pairing check precompiled contract. @@ -171,17 +206,21 @@ Definition alt_bn128_pairing_check : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 (| + ethereum_types.numeric.Uint ~(| (* TODO expression *) |) - |) in + |) ]] in (* TODO statement *) - let* result := ethereum.crypto.alt_bn128.BNF12.["from_int"] (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/shanghai/vm/precompiled_contracts/blake2f.v index 29e808fc5d..9c740d7e14 100644 --- a/coq/ethereum/shanghai/vm/precompiled_contracts/blake2f.v +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/blake2f.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,11 @@ Implementation of the `Blake2` precompiled contract. *) Require ethereum.crypto.blake2. -Require shanghai.vm. -Require shanghai.vm.gas. -Require shanghai.vm.exceptions. +Require ethereum.shanghai.vm. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.exceptions. -Definition blake2f : M unit := +Definition blake2f (evm : Evm) : M unit := (* Writes the Blake2 hash to output. @@ -26,16 +27,20 @@ Definition blake2f : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in (* TODO statement *) - let* blake2b := ethereum.crypto.blake2.Blake2b (| + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| - |) in + |) in + ]] in (* TODO assignment *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, (* TODO expression *) - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/shanghai/vm/precompiled_contracts/ecrecover.v index c1bf9ed28f..e3e0b8b06b 100644 --- a/coq/ethereum/shanghai/vm/precompiled_contracts/ecrecover.v +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/ecrecover.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,11 +17,11 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require shanghai.vm. -Require shanghai.vm.gas. -Require shanghai.vm.memory. +Require ethereum.shanghai.vm. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.memory. -Definition ecrecover : M unit := +Definition ecrecover (evm : Evm) : M unit := (* Decrypts the address using elliptic curve DSA recovery mechanism and writes the address to output. @@ -30,64 +31,80 @@ Definition ecrecover : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* message_hash_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* message_hash := ethereum.crypto.hash.Hash32 (| - message_hash_bytes - |) in - let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + ethereum_types.numeric.U256 ~(| + 32 |) - |) - |) in - let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 + ]] 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 *) - let* address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/shanghai/vm/precompiled_contracts/identity.v index 24644930d5..0d2aceb57a 100644 --- a/coq/ethereum/shanghai/vm/precompiled_contracts/identity.v +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/identity.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,10 @@ Implementation of the `IDENTITY` precompiled contract. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require shanghai.vm. -Require shanghai.vm.gas. +Require ethereum.shanghai.vm. +Require ethereum.shanghai.vm.gas. -Definition identity : M unit := +Definition identity (evm : Evm) : M unit := (* Writes the message data to output. @@ -26,11 +27,15 @@ Definition identity : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/mapping.v b/coq/ethereum/shanghai/vm/precompiled_contracts/mapping.v index 55121afa47..2297fadb16 100644 --- a/coq/ethereum/shanghai/vm/precompiled_contracts/mapping.v +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/mapping.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Mapping of precompiled contracts their implementations. *) Require typing. -Require shanghai.fork_types. -Require shanghai.vm.precompiled_contracts.alt_bn128. -Require shanghai.vm.precompiled_contracts.blake2f. -Require shanghai.vm.precompiled_contracts.ecrecover. -Require shanghai.vm.precompiled_contracts.identity. -Require shanghai.vm.precompiled_contracts.modexp. -Require shanghai.vm.precompiled_contracts.ripemd160. -Require shanghai.vm.precompiled_contracts.sha256. +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.v b/coq/ethereum/shanghai/vm/precompiled_contracts/modexp.v index 9710ce4e6f..170de5910f 100644 --- a/coq/ethereum/shanghai/vm/precompiled_contracts/modexp.v +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/modexp.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,100 +15,120 @@ Implementation of the `MODEXP` precompiled contract. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require shanghai.vm. -Require shanghai.vm.gas. -Require shanghai.vm.memory. +Require ethereum.shanghai.vm. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.memory. -Definition modexp : M unit := +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. *) - let* data := evm.["message"].["data"] in - let* base_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) - |) in - let* exp_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + 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 - let* modulus_length := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* exp_start := (* TODO expression *) in - let* exp_head := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - min (| - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 |), - exp_length + ethereum_types.numeric.U256 ~(| + 32 + |) |) - |) - |) in - do* vm.gas.charge_gas (| + |) 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, - gas_cost (| - base_length, - modulus_length, - exp_length, - exp_head + 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 + |) ]] in (* TODO statement *) - let* base := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - base_length - |) - |) in - let* exp := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - exp_start, - exp_length - |) - |) in - let* modulus_start := (* TODO expression *) in - let* modulus := ethereum_types.numeric.Uint.["from_be_bytes"] (| - memory.buffer_read (| - data, - modulus_start, - modulus_length - |) - |) in + 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 : M unit := +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := (* Estimate the complexity of performing a modular exponentiation. @@ -126,19 +147,23 @@ Definition complexity : M unit := complexity : `Uint` Complexity of performing the operation. *) - let* max_length := max (| - ethereum_types.numeric.Uint (| - base_length - |), - ethereum_types.numeric.Uint (| - modulus_length - |) - |) in - let* words := (* TODO expression *) in + 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 : M unit := +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := (* Calculate the number of iterations required to perform a modular exponentiation. @@ -161,9 +186,9 @@ Definition iterations : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition gas_cost : M unit := +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. @@ -189,15 +214,23 @@ Definition gas_cost : M unit := gas_cost : `Uint` Gas required for performing the operation. *) - let* multiplication_complexity := complexity (| - base_length, - modulus_length - |) in - let* iteration_count := iterations (| - exponent_length, - exponent_head - |) in - let* cost := (* TODO expression *) in - (* TODO statement *) + 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.v b/coq/ethereum/shanghai/vm/precompiled_contracts/ripemd160.v index bc5e73dd3c..fe2c66bbe6 100644 --- a/coq/ethereum/shanghai/vm/precompiled_contracts/ripemd160.v +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/ripemd160.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `RIPEMD160` precompiled contract. *) -Definition ripemd160 : M unit := +Definition ripemd160 (evm : Evm) : M unit := (* Writes the ripemd160 hash to output. @@ -22,21 +23,29 @@ Definition ripemd160 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 - let* hash_bytes := hashlib.["new"] (| - (* TODO expression *), - data - |).["digest"] (| - - |) in - let* padded_hash := left_pad_zero_bytes (| - hash_bytes, - (* TODO expression *) - |) in + |) ]] 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.v b/coq/ethereum/shanghai/vm/precompiled_contracts/sha256.v index da6972d411..3ba3ffe7aa 100644 --- a/coq/ethereum/shanghai/vm/precompiled_contracts/sha256.v +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/sha256.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `SHA256` precompiled contract. *) -Definition sha256 : M unit := +Definition sha256 (evm : Evm) : M unit := (* Writes the sha256 hash to output. @@ -22,11 +23,15 @@ Definition sha256 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/runtime.v b/coq/ethereum/shanghai/vm/runtime.v index 734dcebd63..b72b5a6c10 100644 --- a/coq/ethereum/shanghai/vm/runtime.v +++ b/coq/ethereum/shanghai/vm/runtime.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Runtime Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Runtime related operations used while executing EVM code. Require typing. Require ethereum_types.numeric. -Require shanghai.vm.instructions. +Require ethereum.shanghai.vm.instructions. -Definition get_valid_jump_destinations : M unit := +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := (* Analyze the evm code to obtain the set of valid jump destinations. @@ -38,12 +39,16 @@ Definition get_valid_jump_destinations : M unit := valid_jump_destinations: `Set[Uint]` The set of valid jump destinations in the code. *) - let* valid_jump_destinations := set (| - - |) in - let* pc := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/shanghai/vm/stack.v index bf9f5adca8..017290a34f 100644 --- a/coq/ethereum/shanghai/vm/stack.v +++ b/coq/ethereum/shanghai/vm/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Implementation of the stack operators for the EVM. Require typing. Require ethereum_types.numeric. -Require shanghai.vm.exceptions. +Require ethereum.shanghai.vm.exceptions. -Definition pop : M unit := +Definition pop (stack : (* TODO type *)) : M U256 := (* Pops the top item off of `stack`. @@ -33,9 +34,9 @@ Definition pop : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition push : M unit := +Definition push (stack : (* TODO type *)) (value : U256) : M unit := (* Pushes `value` onto `stack`. @@ -50,4 +51,4 @@ Definition push : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/__init__.v b/coq/ethereum/spurious_dragon/__init__.v index 9dc9482bb6..32cf1d8dc8 100644 --- a/coq/ethereum/spurious_dragon/__init__.v +++ b/coq/ethereum/spurious_dragon/__init__.v @@ -1,3 +1,4 @@ +(* 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 diff --git a/coq/ethereum/spurious_dragon/blocks.v b/coq/ethereum/spurious_dragon/blocks.v index 88505e0073..9297a17de6 100644 --- a/coq/ethereum/spurious_dragon/blocks.v +++ b/coq/ethereum/spurious_dragon/blocks.v @@ -1,3 +1,4 @@ +(* 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 @@ -14,6 +15,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. -Require spurious_dragon.fork_types. -Require spurious_dragon.transactions. +Require ethereum.crypto.hash. +Require ethereum.spurious_dragon.fork_types. +Require ethereum.spurious_dragon.transactions. diff --git a/coq/ethereum/spurious_dragon/bloom.v b/coq/ethereum/spurious_dragon/bloom.v index 878994ceca..29165c028c 100644 --- a/coq/ethereum/spurious_dragon/bloom.v +++ b/coq/ethereum/spurious_dragon/bloom.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Logs Bloom ^^^^^^^^^^^^^^^^^^^ @@ -19,10 +20,10 @@ eliminating blocks and receipts from their search. Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require spurious_dragon.blocks. -Require spurious_dragon.fork_types. +Require ethereum.spurious_dragon.blocks. +Require ethereum.spurious_dragon.fork_types. -Definition add_to_bloom : M unit := +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := (* Add a bloom entry to the bloom filter (`bloom`). @@ -37,13 +38,15 @@ Definition add_to_bloom : M unit := bloom_entry : An entry which is to be added to bloom filter. *) - let* hash := ethereum.crypto.hash.keccak256 (| - bloom_entry - |) in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition logs_bloom : M unit := +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := (* Obtain the logs bloom from a list of log entries. @@ -63,4 +66,4 @@ Definition logs_bloom : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/fork.v b/coq/ethereum/spurious_dragon/fork.v index 1c4f301633..9e689c1ca3 100644 --- a/coq/ethereum/spurious_dragon/fork.v +++ b/coq/ethereum/spurious_dragon/fork.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^ @@ -20,16 +21,18 @@ Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.ethash. Require ethereum.exceptions. -Require spurious_dragon.blocks. -Require spurious_dragon.bloom. -Require spurious_dragon.fork_types. -Require spurious_dragon.state. -Require spurious_dragon.transactions. -Require spurious_dragon.trie. -Require spurious_dragon.utils.message. -Require spurious_dragon.vm.interpreter. - -Definition apply_fork : M unit := +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. @@ -49,9 +52,9 @@ Definition apply_fork : M unit := Upgraded block chain object for this hard fork. *) (* TODO statement *) + M.pure tt. - -Definition get_last_256_block_hashes : M unit := +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. @@ -71,22 +74,28 @@ Definition get_last_256_block_hashes : M unit := recent_block_hashes : `List[Hash32]` Hashes of the recent 256 blocks in order of increasing block number. *) - let* recent_blocks := (* TODO expression *) in - (* TODO statement *) - let* recent_block_hashes := (* TODO expression *) in - (* TODO statement *) - let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *).["header"] - |) - |) in - do* recent_block_hashes.["append"] (| - most_recent_block_hash - |) in - (* TODO statement *) - - -Definition state_transition : M unit := + 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. @@ -108,42 +117,46 @@ Definition state_transition : M unit := block : Block to apply to `chain`. *) - let* parent_header := (* TODO expression *).["header"] in - do* validate_header (| - block.["header"], - parent_header - |) in - do* validate_ommers (| - block.["ommers"], - block.["header"], + 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 - let* apply_body_output := apply_body (| - chain.["state"], - get_last_256_block_hashes (| - chain - |), - block.["header"].["coinbase"], - block.["header"].["number"], - block.["header"].["gas_limit"], - block.["header"].["timestamp"], - block.["header"].["difficulty"], - block.["transactions"], - block.["ommers"], - chain.["chain_id"] - |) in + |) ]] 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* chain.["blocks"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| block - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition validate_header : M unit := +Definition validate_header (header : Header) (parent_header : Header) : M unit := (* Verifies a block header. @@ -165,25 +178,29 @@ Definition validate_header : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* block_difficulty := calculate_block_difficulty (| - header.["number"], - header.["timestamp"], - parent_header.["timestamp"], - parent_header.["difficulty"] - |) in + 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 *) - let* block_parent_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - parent_header - |) - |) in + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in (* TODO statement *) - do* validate_proof_of_work (| + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| header - |) in - + |) ]] in + M.pure tt. -Definition generate_header_hash_for_pow : M unit := +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. @@ -206,11 +223,13 @@ Definition generate_header_hash_for_pow : M unit := hash : `Hash32` The PoW valid rlp hash of the passed in header. *) - let* header_data_without_pow_artefacts := (* TODO expression *) in + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition validate_proof_of_work : M unit := +Definition validate_proof_of_work (header : Header) : M unit := (* Validates the Proof of Work constraints. @@ -225,19 +244,25 @@ Definition validate_proof_of_work : M unit := header : Header of interest. *) - let* header_hash := generate_header_hash_for_pow (| - header - |) in - let* cache := ethereum.ethash.generate_cache (| - header.["number"] - |) in + 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 *) - let* limit := (* TODO expression *) in + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition check_transaction : M unit := +Definition check_transaction (tx : Transaction) (gas_available : Uint) (chain_id : U64) : M Address := (* Check if the transaction is includable in the block. @@ -261,14 +286,16 @@ Definition check_transaction : M unit := If the transaction is not includable. *) (* TODO statement *) - let* sender_address := recover_sender (| - chain_id, - tx - |) in + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition make_receipt : M unit := +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. @@ -289,13 +316,15 @@ Definition make_receipt : M unit := receipt : The receipt for the transaction. *) - let* receipt := blocks.Receipt (| + do* M.assign "receipt" [[ + blocks.Receipt ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition apply_body : M unit := +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. @@ -336,25 +365,31 @@ Definition apply_body : M unit := apply_body_output : `ApplyBodyOutput` Output of applying the block body to the state. *) - let* gas_available := block_gas_limit in + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - do* pay_rewards (| + do* [[ M.get_local ~(| "pay_rewards" |) ~(| state, block_number, coinbase, ommers - |) in - let* block_gas_used := (* TODO expression *) in - let* block_logs_bloom := bloom.logs_bloom (| - block_logs - |) in - (* TODO statement *) - - -Definition validate_ommers : M unit := + |) ]] 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. @@ -376,23 +411,31 @@ Definition validate_ommers : M unit := chain : History and current state. *) - let* block_hash := rlp.["rlp_hash"] (| - block_header - |) in + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* ommers_hashes := (* TODO expression *) in + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* recent_canonical_blocks := (* TODO expression *) in - let* recent_canonical_block_hashes := (* TODO expression *) in + 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 : M unit := +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. @@ -418,21 +461,25 @@ Definition pay_rewards : M unit := ommers : List of ommers mentioned in the current block. *) - let* ommer_count := ethereum_types.numeric.U256 (| - len (| - ommers - |) - |) in - let* miner_reward := (* TODO expression *) in - do* state.create_ether (| + 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, - miner_reward - |) in + M.get_local ~(| "miner_reward" |) + |) ]] in (* TODO statement *) + M.pure tt. - -Definition process_transaction : M unit := +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := (* Execute a transaction against the provided environment. @@ -460,64 +507,92 @@ Definition process_transaction : M unit := Logs generated during execution. *) (* TODO statement *) - let* sender := env.["origin"] in - let* sender_account := state.get_account (| - env.["state"], - sender - |) in - let* gas_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* gas := (* TODO expression *) in - do* state.increment_nonce (| - env.["state"], - sender - |) in - let* sender_balance_after_gas_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - ethereum_types.numeric.U256 (| - sender_balance_after_gas_fee - |) - |) in - let* message := utils.message.prepare_message (| - sender, - tx.["to"], - tx.["value"], - tx.["data"], - gas, - env - |) in - let* output := vm.interpreter.process_message_call (| - message, - env - |) in - let* gas_used := (* TODO expression *) in - let* gas_refund := min (| - (* TODO expression *), - ethereum_types.numeric.Uint (| - output.["refund_counter"] + 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 - let* gas_refund_amount := (* TODO expression *) in - let* transaction_fee := (* TODO expression *) in - let* total_gas_used := (* TODO expression *) in - let* sender_balance_after_refund := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - sender_balance_after_refund - |) in - let* coinbase_balance_after_mining_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - - -Definition validate_transaction : M unit := + |) ]] 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. @@ -545,9 +620,9 @@ Definition validate_transaction : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition calculate_intrinsic_cost : M unit := +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := (* Calculates the gas that is charged before execution is started. @@ -570,13 +645,15 @@ Definition calculate_intrinsic_cost : M unit := verified : `ethereum.base_types.Uint` The intrinsic cost of the transaction. *) - let* data_cost := (* TODO expression *) in + do* M.assign "data_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition recover_sender : M unit := +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := (* Extracts the sender address from a transaction. @@ -603,9 +680,9 @@ Definition recover_sender : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_pre155 : M unit := +Definition signing_hash_pre155 (tx : Transaction) : M Hash32 := (* Compute the hash of a transaction used in a legacy (pre EIP 155) signature. @@ -620,9 +697,9 @@ Definition signing_hash_pre155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition signing_hash_155 : M unit := +Definition signing_hash_155 (tx : Transaction) (chain_id : U64) : M Hash32 := (* Compute the hash of a transaction used in a EIP 155 signature. @@ -639,9 +716,9 @@ Definition signing_hash_155 : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition compute_header_hash : M unit := +Definition compute_header_hash (header : Header) : M Hash32 := (* Computes the hash of a block header. @@ -674,9 +751,9 @@ Definition compute_header_hash : M unit := Hash of the header. *) (* TODO statement *) + M.pure tt. - -Definition check_gas_limit : M unit := +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := (* Validates the gas limit for a block. @@ -704,14 +781,16 @@ Definition check_gas_limit : M unit := check : `bool` True if gas limit constraints are satisfied, False otherwise. *) - let* max_adjustment_delta := (* TODO expression *) in + 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 : M unit := +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. @@ -748,9 +827,15 @@ Definition calculate_block_difficulty : M unit := difficulty : `ethereum.base_types.Uint` Computed difficulty for a block. *) - let* offset := (* TODO expression *) in - let* difficulty := (* TODO expression *) in - let* num_bomb_periods := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - + 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.v b/coq/ethereum/spurious_dragon/fork_types.v index 14de99d5e5..d84cffdf45 100644 --- a/coq/ethereum/spurious_dragon/fork_types.v +++ b/coq/ethereum/spurious_dragon/fork_types.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Types ^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. +Require ethereum.__init__. +Require ethereum.crypto.hash. -Definition encode_account : M unit := +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := (* Encode `Account` dataclass. @@ -26,4 +28,4 @@ Definition encode_account : M unit := encoded without providing a storage root. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/state.v b/coq/ethereum/spurious_dragon/state.v index 1eb8a64d70..3c6bedf8ba 100644 --- a/coq/ethereum/spurious_dragon/state.v +++ b/coq/ethereum/spurious_dragon/state.v @@ -1,3 +1,4 @@ +(* Generated *) (* State ^^^^^ @@ -22,10 +23,10 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require spurious_dragon.fork_types. -Require spurious_dragon.trie. +Require ethereum.spurious_dragon.fork_types. +Require ethereum.spurious_dragon.trie. -Definition close_state : M unit := +Definition close_state (state : State) : M unit := (* Free resources held by the state. Used by optimized implementations to release file descriptors. @@ -33,9 +34,9 @@ Definition close_state : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition begin_transaction : M unit := +Definition begin_transaction (state : State) : M unit := (* Start a state transaction. @@ -47,12 +48,12 @@ Definition begin_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition commit_transaction : M unit := +Definition commit_transaction (state : State) : M unit := (* Commit a state transaction. @@ -61,12 +62,12 @@ Definition commit_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["pop"] (| - - |) in + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + |) ]] in + M.pure tt. -Definition rollback_transaction : M unit := +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. @@ -77,9 +78,9 @@ Definition rollback_transaction : M unit := The state. *) (* TODO assignment *) + M.pure tt. - -Definition get_account : M unit := +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. @@ -99,14 +100,16 @@ Definition get_account : M unit := account : `Account` Account at address. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition get_account_optional : M unit := +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. @@ -123,14 +126,16 @@ Definition get_account_optional : M unit := account : `Account` Account at address. *) - let* account := trie.trie_get (| - state.["_main_trie"], - address - |) in + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition set_account : M unit := +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()`). @@ -144,14 +149,14 @@ Definition set_account : M unit := account : `Account` Account to set at address. *) - do* trie.trie_set (| - state.["_main_trie"], + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), address, account - |) in - + |) ]] in + M.pure tt. -Definition destroy_account : M unit := +Definition destroy_account (state : State) (address : Address) : M unit := (* Completely remove the account at `address` and all of its storage. @@ -166,18 +171,18 @@ Definition destroy_account : M unit := address : `Address` Address of account to destroy. *) - do* destroy_storage (| + do* [[ M.get_local ~(| "destroy_storage" |) ~(| state, address - |) in - do* set_account (| + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - (* TODO expression *) - |) in - + tt + |) ]] in + M.pure tt. -Definition destroy_storage : M unit := +Definition destroy_storage (state : State) (address : Address) : M unit := (* Completely remove the storage at `address`. @@ -189,9 +194,9 @@ Definition destroy_storage : M unit := Address of account whose storage is to be deleted. *) (* TODO statement *) + M.pure tt. - -Definition get_storage : M unit := +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. @@ -210,19 +215,23 @@ Definition get_storage : M unit := value : `U256` Value at the key. *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition set_storage : M unit := +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. @@ -239,19 +248,21 @@ Definition set_storage : M unit := Value to set at the key. *) (* TODO statement *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - do* trie.trie_set (| - trie, + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), key, value - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition storage_root : M unit := +Definition storage_root (state : State) (address : Address) : M Root := (* Calculate the storage root of an account. @@ -269,9 +280,9 @@ Definition storage_root : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition state_root : M unit := +Definition state_root (state : State) : M Root := (* Calculate the state root. @@ -288,9 +299,9 @@ Definition state_root : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition account_exists : M unit := +Definition account_exists (state : State) (address : Address) : M bool := (* Checks if an account exists in the state trie @@ -307,9 +318,9 @@ Definition account_exists : M unit := True if account exists in the state trie, False otherwise *) (* TODO statement *) + M.pure tt. - -Definition account_has_code_or_nonce : M unit := +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := (* Checks if an account has non zero nonce or non empty code @@ -326,14 +337,16 @@ Definition account_has_code_or_nonce : M unit := True if if an account has non zero nonce or non empty code, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_empty : M unit := +Definition is_account_empty (state : State) (address : Address) : M bool := (* Checks if an account has zero nonce, empty code and zero balance. @@ -350,14 +363,16 @@ Definition is_account_empty : M unit := True if if an account has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition account_exists_and_is_empty : M unit := +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. @@ -375,14 +390,16 @@ Definition account_exists_and_is_empty : M unit := True if an account exists and has zero nonce, empty code and zero balance, False otherwise. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition is_account_alive : M unit := +Definition is_account_alive (state : State) (address : Address) : M bool := (* Check whether is an account is both in the state and non empty. @@ -398,49 +415,51 @@ Definition is_account_alive : M unit := is_alive : `bool` True if the account is alive. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition modify_state : M unit := +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := (* Modify an `Account` in the `State`. *) - do* set_account (| + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - ethereum_types.frozen.modify (| - get_account (| + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| state, address |), f |) - |) in - + |) ]] in + M.pure tt. -Definition move_ether : M unit := +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := (* Move funds between accounts. *) (* TODO statement *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, sender_address, - reduce_sender_balance - |) in - do* modify_state (| + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| state, recipient_address, - increase_recipient_balance - |) in + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. - -Definition set_account_balance : M unit := +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := (* Sets the balance of an account. @@ -456,14 +475,14 @@ Definition set_account_balance : M unit := The amount that needs to set in balance. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - set_balance - |) in - + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. -Definition touch_account : M unit := +Definition touch_account (state : State) (address : Address) : M unit := (* Initializes an account to state. @@ -476,9 +495,9 @@ Definition touch_account : M unit := The address of the account that need to initialised. *) (* TODO statement *) + M.pure tt. - -Definition increment_nonce : M unit := +Definition increment_nonce (state : State) (address : Address) : M unit := (* Increments the nonce of an account. @@ -491,14 +510,14 @@ Definition increment_nonce : M unit := Address of the account whose nonce needs to be incremented. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_nonce - |) in - + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. -Definition set_code : M unit := +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := (* Sets Account code. @@ -514,14 +533,14 @@ Definition set_code : M unit := The bytecode that needs to be set. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - write_code - |) in + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. - -Definition create_ether : M unit := +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := (* Add newly created ether to an account. @@ -535,9 +554,9 @@ Definition create_ether : M unit := The amount of ether to be added to the account of interest. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_balance - |) in - + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/transactions.v b/coq/ethereum/spurious_dragon/transactions.v index d9f9943d88..d37ebdefa3 100644 --- a/coq/ethereum/spurious_dragon/transactions.v +++ b/coq/ethereum/spurious_dragon/transactions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, @@ -9,4 +10,4 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require spurious_dragon.fork_types. +Require ethereum.spurious_dragon.fork_types. diff --git a/coq/ethereum/spurious_dragon/trie.v b/coq/ethereum/spurious_dragon/trie.v index 5f0ab29642..3b45315972 100644 --- a/coq/ethereum/spurious_dragon/trie.v +++ b/coq/ethereum/spurious_dragon/trie.v @@ -1,3 +1,4 @@ +(* Generated *) (* State Trie ^^^^^^^^^^ @@ -14,7 +15,7 @@ The state trie is the structure responsible for storing *) -Definition encode_internal_node : M unit := +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 @@ -35,22 +36,24 @@ Definition encode_internal_node : M unit := *) (* TODO statement *) (* TODO statement *) - let* encoded := rlp.["encode"] (| - unencoded - |) in + 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 : M unit := +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 : M unit := +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. @@ -66,9 +69,9 @@ Definition copy_trie : M unit := A copy of the trie. *) (* TODO statement *) + M.pure tt. - -Definition trie_set : M unit := +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := (* Stores an item in a Merkle Trie. @@ -85,9 +88,9 @@ Definition trie_set : M unit := Node to insert at `key`. *) (* TODO statement *) + M.pure tt. - -Definition trie_get : M unit := +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := (* Gets an item from the Merkle Trie. @@ -106,17 +109,17 @@ Definition trie_get : M unit := Node at `key` in the trie. *) (* TODO statement *) + M.pure tt. - -Definition common_prefix_length : M unit := +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 : M unit := +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := (* Compresses nibble-list into a standard byte array with a flag. @@ -150,14 +153,16 @@ Definition nibble_list_to_compact : M unit := compressed : `bytearray` Compact byte array. *) - let* compact := bytearray (| + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition bytes_to_nibble_list : M unit := +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := (* Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). @@ -171,14 +176,16 @@ Definition bytes_to_nibble_list : M unit := nibble_list : `Bytes` The `Bytes` in nibble-list format. *) - let* nibble_list := bytearray (| - (* TODO expression *) - |) in + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _prepare_trie : M unit := +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. @@ -199,9 +206,9 @@ Definition _prepare_trie : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition root : M unit := +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := (* Computes the root of a modified merkle patricia trie (MPT). @@ -219,22 +226,26 @@ Definition root : M unit := root : `.fork_types.Root` MPT root of the underlying key-value pairs. *) - let* obj := _prepare_trie (| - trie, - get_storage_root - |) in - let* root_node := encode_internal_node (| - patricialize (| - obj, - Uint (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) + M.pure tt. - -Definition patricialize : M unit := +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := (* Structural composition function. @@ -254,21 +265,29 @@ Definition patricialize : M unit := Root node of `obj`. *) (* TODO statement *) - let* arbitrary_key := next (| - iter (| - obj - |) - |) in + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in (* TODO statement *) - let* substring := (* TODO expression *) in - let* prefix_length := len (| - substring - |) in + 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 *) - let* value := (* TODO expression *) in + do* M.assign "value" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/utils/__init__.v b/coq/ethereum/spurious_dragon/utils/__init__.v index beff4482b1..7f30fe939b 100644 --- a/coq/ethereum/spurious_dragon/utils/__init__.v +++ b/coq/ethereum/spurious_dragon/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions unique to this particular fork. *) diff --git a/coq/ethereum/spurious_dragon/utils/address.v b/coq/ethereum/spurious_dragon/utils/address.v index de189a64ef..ae256d9d48 100644 --- a/coq/ethereum/spurious_dragon/utils/address.v +++ b/coq/ethereum/spurious_dragon/utils/address.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,9 +18,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require spurious_dragon.fork_types. +Require ethereum.__init__. +Require ethereum.spurious_dragon.fork_types. -Definition to_address : M unit := +Definition to_address (data : (* TODO type *)) : M Address := (* Convert a Uint or U256 value to a valid address (20 bytes). @@ -34,9 +36,9 @@ Definition to_address : M unit := The obtained address. *) (* TODO statement *) + M.pure tt. - -Definition compute_contract_address : M unit := +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := (* Computes address of the new account that needs to be created. @@ -53,15 +55,21 @@ Definition compute_contract_address : M unit := address: `ethereum.spurious_dragon.fork_types.Address` The computed address of the new account. *) - let* computed_address := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *) - |) - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/spurious_dragon/utils/hexadecimal.v index 6a6aeb82fb..8e69a91904 100644 --- a/coq/ethereum/spurious_dragon/utils/hexadecimal.v +++ b/coq/ethereum/spurious_dragon/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Spurious Dragon types. *) Require ethereum.utils.hexadecimal. -Require spurious_dragon.fork_types. +Require ethereum.spurious_dragon.fork_types. -Definition hex_to_root : M unit := +Definition hex_to_root (hex_string : str) : M Root := (* Convert hex string to trie root. @@ -31,9 +32,9 @@ Definition hex_to_root : M unit := Trie root obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bloom : M unit := +Definition hex_to_bloom (hex_string : str) : M Bloom := (* Convert hex string to bloom. @@ -48,9 +49,9 @@ Definition hex_to_bloom : M unit := Bloom obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_address : M unit := +Definition hex_to_address (hex_string : str) : M Address := (* Convert hex string to Address (20 bytes). @@ -65,4 +66,4 @@ Definition hex_to_address : M unit := The address obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/utils/message.v b/coq/ethereum/spurious_dragon/utils/message.v index e2397508c4..1a47b5c972 100644 --- a/coq/ethereum/spurious_dragon/utils/message.v +++ b/coq/ethereum/spurious_dragon/utils/message.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For The Message Data-structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,12 +17,12 @@ specification. Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require spurious_dragon.fork_types. -Require spurious_dragon.state. -Require spurious_dragon.vm. -Require spurious_dragon.utils.address. +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 : M unit := +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. @@ -53,4 +54,4 @@ Definition prepare_message : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/__init__.v b/coq/ethereum/spurious_dragon/vm/__init__.v index 995a573d09..de947ecf97 100644 --- a/coq/ethereum/spurious_dragon/vm/__init__.v +++ b/coq/ethereum/spurious_dragon/vm/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,12 +19,12 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require spurious_dragon.blocks. -Require spurious_dragon.fork_types. -Require spurious_dragon.state. -Require spurious_dragon.vm.precompiled_contracts. +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 : M unit := +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of a successful `child_evm` into the parent `evm`. @@ -34,19 +35,25 @@ Definition incorporate_child_on_success : M unit := 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 *) - (* TODO statement *) - (* TODO statement *) - do* evm.["accounts_to_delete"].["update"] (| - child_evm.["accounts_to_delete"] - |) in - do* evm.["touched_accounts"].["update"] (| - child_evm.["touched_accounts"] - |) in - (* TODO statement *) + M.pure tt. - -Definition incorporate_child_on_error : M unit := +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. @@ -59,5 +66,7 @@ Definition incorporate_child_on_error : M unit := *) (* TODO statement *) (* 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.v b/coq/ethereum/spurious_dragon/vm/exceptions.v index 1784494410..47e26555d5 100644 --- a/coq/ethereum/spurious_dragon/vm/exceptions.v +++ b/coq/ethereum/spurious_dragon/vm/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Exceptions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/spurious_dragon/vm/gas.v b/coq/ethereum/spurious_dragon/vm/gas.v index f4e13617c8..aad2c0de80 100644 --- a/coq/ethereum/spurious_dragon/vm/gas.v +++ b/coq/ethereum/spurious_dragon/vm/gas.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Gas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,9 +18,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.trace. Require ethereum.utils.numeric. -Require spurious_dragon.vm.exceptions. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.exceptions. -Definition charge_gas : M unit := +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := (* Subtracts `amount` from `evm.gas_left`. @@ -31,18 +33,18 @@ Definition charge_gas : M unit := The amount of gas the current operation requires. *) - do* ethereum.trace.evm_trace (| + do* [[ ethereum.trace.evm_trace ~(| evm, - ethereum.trace.GasAndRefund (| - int (| + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| amount |) |) - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_memory_gas_cost : M unit := +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, @@ -58,14 +60,22 @@ Definition calculate_memory_gas_cost : M unit := total_gas_cost : `ethereum.base_types.Uint` The gas cost for storing data in memory. *) - let* size_in_words := (* TODO expression *) in - let* linear_cost := (* TODO expression *) in - let* quadratic_cost := (* TODO expression *) in - let* total_gas_cost := (* TODO expression *) in + 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 : M unit := +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := (* Calculates the gas amount to extend memory @@ -81,22 +91,28 @@ Definition calculate_gas_extend_memory : M unit := ------- extend_memory: `ExtendMemory` *) - let* size_to_extend := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* to_be_paid := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* current_size := ethereum_types.numeric.Uint (| - len (| - memory - |) - |) in + 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 : M unit := +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. @@ -122,18 +138,22 @@ Definition calculate_message_call_gas : M unit := ------- message_call_gas: `MessageCallGas` *) - let* call_stipend := (* TODO expression *) in + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* gas := min (| - gas, - max_message_call_gas (| - (* TODO expression *) - |) - |) in + 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 : M unit := +Definition max_message_call_gas (gas : Uint) : M Uint := (* Calculates the maximum gas that is allowed for making a message call @@ -148,4 +168,4 @@ Definition max_message_call_gas : M unit := The maximum gas allowed for making the message-call. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/instructions/__init__.v b/coq/ethereum/spurious_dragon/vm/instructions/__init__.v index b36b1ebfef..cbd7e7e63a 100644 --- a/coq/ethereum/spurious_dragon/vm/instructions/__init__.v +++ b/coq/ethereum/spurious_dragon/vm/instructions/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* EVM Instruction Encoding (Opcodes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/spurious_dragon/vm/instructions/arithmetic.v b/coq/ethereum/spurious_dragon/vm/instructions/arithmetic.v index 1fafedb5e9..c9161c970e 100644 --- a/coq/ethereum/spurious_dragon/vm/instructions/arithmetic.v +++ b/coq/ethereum/spurious_dragon/vm/instructions/arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,11 @@ Implementations of the EVM Arithmetic instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require spurious_dragon.vm.gas. -Require spurious_dragon.vm.stack. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.stack. -Definition add : M unit := +Definition add (evm : Evm) : M unit := (* Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -28,27 +30,37 @@ Definition add : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_add"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sub (evm : Evm) : M unit := (* Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -59,27 +71,37 @@ Definition sub : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_sub"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mul (evm : Evm) : M unit := (* Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -90,27 +112,37 @@ Definition mul : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_mul"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition div (evm : Evm) : M unit := (* Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -121,25 +153,33 @@ Definition div : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |) in - let* divisor := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - quotient - |) 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 : M unit := +Definition sdiv (evm : Evm) : M unit := (* Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -150,31 +190,39 @@ Definition sdiv : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* divisor := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - quotient + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mod : M unit := +Definition mod (evm : Evm) : M unit := (* Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -185,25 +233,33 @@ Definition mod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - remainder - |) in + |) ]] 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 : M unit := +Definition smod (evm : Evm) : M unit := (* Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -214,31 +270,39 @@ Definition smod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* y := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - remainder + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition addmod : M unit := +Definition addmod (evm : Evm) : M unit := (* Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -249,34 +313,44 @@ Definition addmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +Definition mulmod (evm : Evm) : M unit := (* Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -287,34 +361,44 @@ Definition mulmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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 : M unit := +Definition exp (evm : Evm) : M unit := (* Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -325,39 +409,53 @@ Definition exp : M unit := The current EVM frame. *) - let* base := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent_bits := exponent.["bit_length"] (| - - |) in - let* exponent_bytes := (* TODO expression *) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - pow (| - base, - exponent, - (* 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 - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition signextend : M unit := +Definition signextend (evm : Evm) : M unit := (* Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -368,20 +466,28 @@ Definition signextend : M unit := The current EVM frame. *) - let* byte_num := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/spurious_dragon/vm/instructions/bitwise.v index b8fa64fff5..fb45d69e5b 100644 --- a/coq/ethereum/spurious_dragon/vm/instructions/bitwise.v +++ b/coq/ethereum/spurious_dragon/vm/instructions/bitwise.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Bitwise Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM bitwise instructions. *) Require ethereum_types.numeric. -Require spurious_dragon.vm.gas. -Require spurious_dragon.vm.stack. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.stack. -Definition bitwise_and : M unit := +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. @@ -27,24 +29,32 @@ Definition bitwise_and : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_or : M unit := + |) ]] 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. @@ -55,24 +65,32 @@ Definition bitwise_or : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_xor : M unit := + |) ]] 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. @@ -83,24 +101,32 @@ Definition bitwise_xor : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_not : M unit := + |) ]] 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. @@ -111,21 +137,27 @@ Definition bitwise_not : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition get_byte : M unit := + |) ]] 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 @@ -137,20 +169,28 @@ Definition get_byte : M unit := The current EVM frame. *) - let* byte_index := stack.pop (| - evm.["stack"] - |) in - let* word := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/spurious_dragon/vm/instructions/block.v index bf55cc4aa6..93b8b65618 100644 --- a/coq/ethereum/spurious_dragon/vm/instructions/block.v +++ b/coq/ethereum/spurious_dragon/vm/instructions/block.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Block Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM block instructions. *) Require ethereum_types.numeric. -Require spurious_dragon.vm.gas. -Require spurious_dragon.vm.stack. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.stack. -Definition block_hash : M unit := +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. @@ -27,27 +29,35 @@ Definition block_hash : M unit := The current EVM frame. *) - let* block_number := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* max_block_number := (* TODO expression *) in + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition coinbase : M unit := +Definition coinbase (evm : Evm) : M unit := (* Push the current block's beneficiary address (address of the block miner) onto the stack. @@ -62,20 +72,24 @@ Definition coinbase : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["coinbase"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition timestamp : M unit := +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. @@ -90,18 +104,22 @@ Definition timestamp : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["env"].["time"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition number (evm : Evm) : M unit := (* Push the current block's number onto the stack. @@ -115,20 +133,24 @@ Definition number : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["number"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition difficulty : M unit := +Definition difficulty (evm : Evm) : M unit := (* Push the current block's difficulty onto the stack. @@ -142,20 +164,24 @@ Definition difficulty : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["difficulty"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_limit : M unit := +Definition gas_limit (evm : Evm) : M unit := (* Push the current block's gas limit onto the stack. @@ -169,15 +195,19 @@ Definition gas_limit : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_limit"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/spurious_dragon/vm/instructions/comparison.v index 574749ebac..9ffa78c95f 100644 --- a/coq/ethereum/spurious_dragon/vm/instructions/comparison.v +++ b/coq/ethereum/spurious_dragon/vm/instructions/comparison.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Comparison Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM Comparison instructions. *) Require ethereum_types.numeric. -Require spurious_dragon.vm.gas. -Require spurious_dragon.vm.stack. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.stack. -Definition less_than : M unit := +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. @@ -27,27 +29,37 @@ Definition less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_less_than : M unit := + |) ]] 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. @@ -57,31 +69,41 @@ Definition signed_less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition greater_than : M unit := + |) ]] 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. @@ -92,27 +114,37 @@ Definition greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_greater_than : M unit := + |) ]] 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. @@ -122,31 +154,41 @@ Definition signed_greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition equal : M unit := + |) ]] 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. @@ -157,27 +199,37 @@ Definition equal : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition is_zero : M unit := + |) ]] 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. @@ -188,19 +240,27 @@ Definition is_zero : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/spurious_dragon/vm/instructions/control_flow.v index f3652fcd26..dcef66f3fb 100644 --- a/coq/ethereum/spurious_dragon/vm/instructions/control_flow.v +++ b/coq/ethereum/spurious_dragon/vm/instructions/control_flow.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Control Flow Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM control flow instructions. *) Require ethereum_types.numeric. -Require spurious_dragon.vm.gas. -Require spurious_dragon.vm.exceptions. -Require spurious_dragon.vm.stack. +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 : M unit := +Definition stop (evm : Evm) : M unit := (* Stop further execution of EVM code. @@ -29,10 +31,14 @@ Definition stop : M unit := (* TODO statement *) (* TODO statement *) (* TODO assignment *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jump : M unit := +Definition jump (evm : Evm) : M unit := (* Alter the program counter to the location specified by the top of the stack. @@ -43,20 +49,22 @@ Definition jump : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition jumpi : M unit := +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 @@ -68,23 +76,27 @@ Definition jumpi : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* conditional_value := stack.pop (| - evm.["stack"] - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition pc : M unit := +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. @@ -96,20 +108,24 @@ Definition pc : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["pc"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_left : M unit := +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. @@ -121,20 +137,24 @@ Definition gas_left : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["gas_left"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jumpdest : M unit := +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 @@ -147,10 +167,14 @@ Definition jumpdest : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_JUMPDEST - |) in - (* TODO statement *) + |) ]] 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.v b/coq/ethereum/spurious_dragon/vm/instructions/environment.v index fdc679afce..676093a15c 100644 --- a/coq/ethereum/spurious_dragon/vm/instructions/environment.v +++ b/coq/ethereum/spurious_dragon/vm/instructions/environment.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,13 +15,14 @@ Implementations of the EVM environment related instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require spurious_dragon.state. -Require spurious_dragon.utils.address. -Require spurious_dragon.vm.memory. -Require spurious_dragon.vm.gas. -Require spurious_dragon.vm.stack. - -Definition address : M unit := +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. @@ -31,20 +33,24 @@ Definition address : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["current_target"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition balance : M unit := +Definition balance (evm : Evm) : M unit := (* Pushes the balance of the given account onto the stack. @@ -54,27 +60,35 @@ Definition balance : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* balance := state.get_account (| - evm.["env"].["state"], - address - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +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. @@ -86,20 +100,24 @@ Definition origin : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["origin"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition caller : M unit := +Definition caller (evm : Evm) : M unit := (* Pushes the address of the caller onto the stack. @@ -110,20 +128,24 @@ Definition caller : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["caller"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition callvalue : M unit := +Definition callvalue (evm : Evm) : M unit := (* Push the value (in wei) sent with the call onto the stack. @@ -134,18 +156,22 @@ Definition callvalue : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["message"].["value"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition calldataload (evm : Evm) : M unit := (* Push a word (32 bytes) of the input data belonging to the current environment onto the stack. @@ -156,30 +182,38 @@ Definition calldataload : M unit := The current EVM frame. *) - let* start_index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - start_index, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] 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* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - value + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 |) - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition calldatasize : M unit := +Definition calldatasize (evm : Evm) : M unit := (* Push the size of input data in current environment onto the stack. @@ -190,22 +224,26 @@ Definition calldatasize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["message"].["data"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition calldatacopy : M unit := +Definition calldatacopy (evm : Evm) : M unit := (* Copy a portion of the input data in current environment to memory. @@ -218,40 +256,60 @@ Definition calldatacopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* data_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - data_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition codesize (evm : Evm) : M unit := (* Push the size of code running in current environment onto the stack. @@ -262,22 +320,26 @@ Definition codesize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["code"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition codecopy : M unit := +Definition codecopy (evm : Evm) : M unit := (* Copy a portion of the code in current environment to memory. @@ -290,40 +352,60 @@ Definition codecopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["code"], - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition gasprice (evm : Evm) : M unit := (* Push the gas price used in current environment onto the stack. @@ -334,20 +416,24 @@ Definition gasprice : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_price"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition extcodesize : M unit := +Definition extcodesize (evm : Evm) : M unit := (* Push the code size of a given account onto the stack. @@ -357,31 +443,39 @@ Definition extcodesize : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* codesize := ethereum_types.numeric.U256 (| - len (| - state.get_account (| - evm.["env"].["state"], - address - |).["code"] + |) ]] 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 - do* stack.push (| - evm.["stack"], - codesize - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition extcodecopy : M unit := +Definition extcodecopy (evm : Evm) : M unit := (* Copy a portion of an account's code to memory. @@ -391,44 +485,68 @@ Definition extcodecopy : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* code := state.get_account (| - evm.["env"].["state"], - address - |).["code"] in - let* value := vm.memory.buffer_read (| - code, - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/spurious_dragon/vm/instructions/keccak.v index 4c744eefe2..b1428ca4d7 100644 --- a/coq/ethereum/spurious_dragon/vm/instructions/keccak.v +++ b/coq/ethereum/spurious_dragon/vm/instructions/keccak.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Keccak Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM keccak instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require spurious_dragon.vm.gas. -Require spurious_dragon.vm.memory. -Require spurious_dragon.vm.stack. +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 : M unit := +Definition keccak (evm : Evm) : M unit := (* Pushes to the stack the Keccak-256 hash of a region of memory. @@ -32,36 +34,56 @@ Definition keccak : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* word_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in - let* hash := ethereum.crypto.hash.keccak256 (| - data - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/spurious_dragon/vm/instructions/log.v index 3a5126b702..1759e4d4ba 100644 --- a/coq/ethereum/spurious_dragon/vm/instructions/log.v +++ b/coq/ethereum/spurious_dragon/vm/instructions/log.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Logging Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,12 +15,13 @@ Implementations of the EVM logging instructions. Require functools. Require ethereum_types.numeric. -Require spurious_dragon.blocks. -Require spurious_dragon.vm.gas. -Require spurious_dragon.vm.memory. -Require spurious_dragon.vm.stack. +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 : M unit := +Definition log_n (evm : Evm) (num_topics : U256) : M unit := (* Appends a log entry, having `num_topics` topics, to the evm logs. @@ -34,26 +36,42 @@ Definition log_n : M unit := The number of topics to be included in the log entry. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* topics := (* TODO expression *) in + 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 *) - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - let* log_entry := blocks.Log (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "log_entry" [[ + blocks.Log ~(| - |) in + |) in + ]] in (* TODO assignment *) - (* 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/memory.v b/coq/ethereum/spurious_dragon/vm/instructions/memory.v index 128b299841..43f96f693f 100644 --- a/coq/ethereum/spurious_dragon/vm/instructions/memory.v +++ b/coq/ethereum/spurious_dragon/vm/instructions/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM Memory instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require spurious_dragon.vm.gas. -Require spurious_dragon.vm.memory. -Require spurious_dragon.vm.stack. +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 : M unit := +Definition mstore (evm : Evm) : M unit := (* Stores a word to memory. This also expands the memory, if the memory is @@ -30,32 +32,44 @@ Definition mstore : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* memory.memory_write (| - evm.["memory"], - start_position, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mstore8 (evm : Evm) : M unit := (* Stores a byte to memory. This also expands the memory, if the memory is @@ -67,33 +81,47 @@ Definition mstore8 : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ (* TODO expression *) - |) in - do* memory.memory_write (| - evm.["memory"], - start_position, - normalized_bytes_value - |) in - (* TODO statement *) - + ]] 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 : M unit := +Definition mload (evm : Evm) : M unit := (* Load word from memory. @@ -103,35 +131,47 @@ Definition mload : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.memory_read_bytes (| - evm.["memory"], - start_position, - ethereum_types.numeric.U256 (| - (* 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 - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition msize : M unit := +Definition msize (evm : Evm) : M unit := (* Push the size of active memory in bytes onto the stack. @@ -142,17 +182,21 @@ Definition msize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["memory"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/spurious_dragon/vm/instructions/stack.v index 5c85c4ed9e..04e12c60a6 100644 --- a/coq/ethereum/spurious_dragon/vm/instructions/stack.v +++ b/coq/ethereum/spurious_dragon/vm/instructions/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM stack related instructions. Require functools. Require ethereum_types.numeric. -Require spurious_dragon.vm.exceptions. -Require spurious_dragon.vm.gas. -Require spurious_dragon.vm.memory. +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 : M unit := +Definition pop (evm : Evm) : M unit := (* Remove item from stack. @@ -28,18 +30,22 @@ Definition pop : M unit := The current EVM frame. *) - do* stack.["pop"] (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in + |) ]] in (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition push_n : M unit := +Definition push_n (evm : Evm) (num_bytes : int) : M unit := (* Pushes a N-byte immediate onto the stack. @@ -54,29 +60,33 @@ Definition push_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - evm.["code"], - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - num_bytes + |) ]] 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 - do* stack.["push"] (| - evm.["stack"], - data_to_push - |) in - (* TODO statement *) - - -Definition dup_n : M unit := + |) 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. @@ -91,20 +101,26 @@ Definition dup_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - let* data_to_duplicate := (* TODO expression *) in - do* stack.["push"] (| - evm.["stack"], - data_to_duplicate - |) 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 : M unit := +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. @@ -123,11 +139,15 @@ Definition swap_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - (* 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/storage.v b/coq/ethereum/spurious_dragon/vm/instructions/storage.v index 77a9c099d2..b4589d1612 100644 --- a/coq/ethereum/spurious_dragon/vm/instructions/storage.v +++ b/coq/ethereum/spurious_dragon/vm/instructions/storage.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Storage Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM storage related instructions. *) Require ethereum_types.numeric. -Require spurious_dragon.state. -Require spurious_dragon.vm.gas. -Require spurious_dragon.vm.stack. +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 : M unit := +Definition sload (evm : Evm) : M unit := (* Loads to the stack, the value corresponding to a certain key from the storage of the current account. @@ -28,28 +30,36 @@ Definition sload : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_SLOAD - |) in - let* value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sstore (evm : Evm) : M unit := (* Stores a value at a certain key in the current context's storage. @@ -59,30 +69,40 @@ Definition sstore : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in - let* current_value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in + |) 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - do* state.set_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key, - new_value - |) in - (* TODO statement *) - + 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.v b/coq/ethereum/spurious_dragon/vm/instructions/system.v index 27d5f37875..a935f84563 100644 --- a/coq/ethereum/spurious_dragon/vm/instructions/system.v +++ b/coq/ethereum/spurious_dragon/vm/instructions/system.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) System Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,14 +15,15 @@ Implementations of the EVM system related instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require spurious_dragon.fork_types. -Require spurious_dragon.state. -Require spurious_dragon.utils.address. -Require spurious_dragon.vm.gas. -Require spurious_dragon.vm.memory. -Require spurious_dragon.vm.stack. +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 : M unit := +Definition create (evm : Evm) : M unit := (* Creates a new account with associated code. @@ -31,47 +33,71 @@ Definition create : M unit := The current EVM frame. *) (* TODO statement *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - let* create_message_gas := gas.max_message_call_gas (| - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |) - |) in - (* TODO statement *) - (* TODO statement *) - let* sender_address := evm.["message"].["current_target"] in - let* sender := state.get_account (| - evm.["env"].["state"], - sender_address - |) in - let* contract_address := utils.address.compute_contract_address (| - evm.["message"].["current_target"], - state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["nonce"] - |) in - (* TODO statement *) + |) ]] 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_ : M unit := +Definition return_ (evm : Evm) : M unit := (* Halts execution returning output data. @@ -80,65 +106,83 @@ Definition return_ : M unit := evm : The current EVM frame. *) - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) + |) ]] 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 : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_input_start_position, - memory_input_size - |) in - let* code := state.get_account (| - evm.["env"].["state"], - code_address - |).["code"] in - let* child_message := Message (| + 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 - let* child_evm := process_message (| - child_message, - evm.["env"] - |) in + |) 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 *) - let* actual_output_size := min (| - memory_output_size, - ethereum_types.numeric.U256 (| - len (| - child_evm.["output"] + 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 - do* memory.memory_write (| - evm.["memory"], + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), memory_output_start_position, (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition call : M unit := +Definition call (evm : Evm) : M unit := (* Message-call into an account. @@ -147,60 +191,90 @@ Definition call : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* create_gas_cost := (* TODO expression *) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition callcode (evm : Evm) : M unit := (* Message-call into this account with alternative account’s code. @@ -209,60 +283,90 @@ Definition callcode : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* to := evm.["message"].["current_target"] in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition selfdestruct (evm : Evm) : M unit := (* Halt execution and register account for later deletion. @@ -271,51 +375,65 @@ Definition selfdestruct : M unit := evm : The current EVM frame. *) - let* beneficiary := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* gas_cost := gas.GAS_SELF_DESTRUCT in + 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 *) - let* originator := evm.["message"].["current_target"] in - let* refunded_accounts := evm.["accounts_to_delete"] in - let* parent_evm := evm.["message"].["parent_evm"] 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - let* beneficiary_balance := state.get_account (| - evm.["env"].["state"], - beneficiary - |).["balance"] in - let* originator_balance := state.get_account (| - evm.["env"].["state"], - originator - |).["balance"] in - do* state.set_account_balance (| - evm.["env"].["state"], - beneficiary, + 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 (| - evm.["env"].["state"], - originator, - ethereum_types.numeric.U256 (| - (* 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* evm.["accounts_to_delete"].["add"] (| - originator - |) in + |) ]] 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 : M unit := +Definition delegatecall (evm : Evm) : M unit := (* Message-call into an account. @@ -324,60 +442,82 @@ Definition delegatecall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - gas.GAS_CALL - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - evm.["message"].["value"], - evm.["message"].["caller"], - evm.["message"].["current_target"], - code_address, - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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.v b/coq/ethereum/spurious_dragon/vm/interpreter.v index f3eec05c02..c2df93da24 100644 --- a/coq/ethereum/spurious_dragon/vm/interpreter.v +++ b/coq/ethereum/spurious_dragon/vm/interpreter.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Interpreter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +18,18 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.trace. -Require spurious_dragon.blocks. -Require spurious_dragon.fork_types. -Require spurious_dragon.state. -Require spurious_dragon.vm. -Require spurious_dragon.vm.gas. -Require spurious_dragon.vm.precompiled_contracts.mapping. -Require spurious_dragon.vm.exceptions. -Require spurious_dragon.vm.instructions. -Require spurious_dragon.vm.runtime. - -Definition process_message_call : M unit := +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`. @@ -47,19 +49,21 @@ Definition process_message_call : M unit := *) (* TODO statement *) (* TODO statement *) - let* tx_end := ethereum.trace.TransactionEnd (| - (* TODO expression *), - evm.["output"], - evm.["error"] - |) in - do* ethereum.trace.evm_trace (| - evm, - tx_end - |) in + 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 : M unit := +Definition process_create_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -75,26 +79,28 @@ Definition process_create_message : M unit := evm: :py:class:`~ethereum.spurious_dragon.vm.Evm` Items containing execution specific objects. *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.destroy_storage (| - env.["state"], - message.["current_target"] - |) in - do* state.increment_nonce (| - env.["state"], - message.["current_target"] - |) in - let* evm := process_message (| - message, - env - |) in + 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 : M unit := +Definition process_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -111,23 +117,25 @@ Definition process_message : M unit := Items containing execution specific objects *) (* TODO statement *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.touch_account (| - env.["state"], - message.["current_target"] - |) in + 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 *) - let* evm := execute_code (| - message, - env - |) in + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition execute_code : M unit := +Definition execute_code (message : Message) (env : Environment) : M Evm := (* Executes bytecode present in the `message`. @@ -143,13 +151,19 @@ Definition execute_code : M unit := evm: `ethereum.vm.EVM` Items containing execution specific objects *) - let* code := message.["code"] in - let* valid_jump_destinations := runtime.get_valid_jump_destinations (| - code - |) in - let* evm := Evm (| - - |) in + 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.v b/coq/ethereum/spurious_dragon/vm/memory.v index 94b6a44639..88b516318f 100644 --- a/coq/ethereum/spurious_dragon/vm/memory.v +++ b/coq/ethereum/spurious_dragon/vm/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.byte. -Definition memory_write : M unit := +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := (* Writes to memory. @@ -30,9 +31,9 @@ Definition memory_write : M unit := Data to write to memory. *) (* TODO assignment *) + M.pure tt. - -Definition memory_read_bytes : M unit := +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := (* Read bytes from memory. @@ -51,9 +52,9 @@ Definition memory_read_bytes : M unit := Data read from memory. *) (* TODO statement *) + M.pure tt. - -Definition buffer_read : M unit := +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := (* Read bytes from a buffer. Padding with zeros if necessary. @@ -72,4 +73,4 @@ Definition buffer_read : M unit := Data read from memory. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.v b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.v index 3f74475666..cad0c38372 100644 --- a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,4 +14,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require spurious_dragon.utils.hexadecimal. +Require ethereum.spurious_dragon.utils.hexadecimal. diff --git a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.v index b59ea16dbe..c07f765497 100644 --- a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.v +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,11 +17,11 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require spurious_dragon.vm. -Require spurious_dragon.vm.gas. -Require spurious_dragon.vm.memory. +Require ethereum.spurious_dragon.vm. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.memory. -Definition ecrecover : M unit := +Definition ecrecover (evm : Evm) : M unit := (* Decrypts the address using elliptic curve DSA recovery mechanism and writes the address to output. @@ -30,64 +31,80 @@ Definition ecrecover : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* message_hash_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* message_hash := ethereum.crypto.hash.Hash32 (| - message_hash_bytes - |) in - let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + ethereum_types.numeric.U256 ~(| + 32 |) - |) - |) in - let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 + ]] 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 *) - let* address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/identity.v index 3743df8848..4ec9a2cd0a 100644 --- a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/identity.v +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/identity.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,10 @@ Implementation of the `IDENTITY` precompiled contract. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require spurious_dragon.vm. -Require spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm. +Require ethereum.spurious_dragon.vm.gas. -Definition identity : M unit := +Definition identity (evm : Evm) : M unit := (* Writes the message data to output. @@ -26,11 +27,15 @@ Definition identity : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.v b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.v index aef3392938..d0224bfeb5 100644 --- a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.v +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,8 +14,9 @@ Mapping of precompiled contracts their implementations. *) Require typing. -Require spurious_dragon.fork_types. -Require spurious_dragon.vm.precompiled_contracts.ecrecover. -Require spurious_dragon.vm.precompiled_contracts.identity. -Require spurious_dragon.vm.precompiled_contracts.ripemd160. -Require spurious_dragon.vm.precompiled_contracts.sha256. +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.v b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.v index bc5e73dd3c..fe2c66bbe6 100644 --- a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.v +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `RIPEMD160` precompiled contract. *) -Definition ripemd160 : M unit := +Definition ripemd160 (evm : Evm) : M unit := (* Writes the ripemd160 hash to output. @@ -22,21 +23,29 @@ Definition ripemd160 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 - let* hash_bytes := hashlib.["new"] (| - (* TODO expression *), - data - |).["digest"] (| - - |) in - let* padded_hash := left_pad_zero_bytes (| - hash_bytes, - (* TODO expression *) - |) in + |) ]] 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.v b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.v index da6972d411..3ba3ffe7aa 100644 --- a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.v +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `SHA256` precompiled contract. *) -Definition sha256 : M unit := +Definition sha256 (evm : Evm) : M unit := (* Writes the sha256 hash to output. @@ -22,11 +23,15 @@ Definition sha256 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/runtime.v b/coq/ethereum/spurious_dragon/vm/runtime.v index 3641ac12f8..30aa2dc40d 100644 --- a/coq/ethereum/spurious_dragon/vm/runtime.v +++ b/coq/ethereum/spurious_dragon/vm/runtime.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Runtime Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Runtime related operations used while executing EVM code. Require typing. Require ethereum_types.numeric. -Require spurious_dragon.vm.instructions. +Require ethereum.spurious_dragon.vm.instructions. -Definition get_valid_jump_destinations : M unit := +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := (* Analyze the evm code to obtain the set of valid jump destinations. @@ -38,12 +39,16 @@ Definition get_valid_jump_destinations : M unit := valid_jump_destinations: `Set[Uint]` The set of valid jump destinations in the code. *) - let* valid_jump_destinations := set (| - - |) in - let* pc := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/spurious_dragon/vm/stack.v index ad7f0e3e24..2d22e100f8 100644 --- a/coq/ethereum/spurious_dragon/vm/stack.v +++ b/coq/ethereum/spurious_dragon/vm/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Implementation of the stack operators for the EVM. Require typing. Require ethereum_types.numeric. -Require spurious_dragon.vm.exceptions. +Require ethereum.spurious_dragon.vm.exceptions. -Definition pop : M unit := +Definition pop (stack : (* TODO type *)) : M U256 := (* Pops the top item off of `stack`. @@ -33,9 +34,9 @@ Definition pop : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition push : M unit := +Definition push (stack : (* TODO type *)) (value : U256) : M unit := (* Pushes `value` onto `stack`. @@ -50,4 +51,4 @@ Definition push : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/__init__.v b/coq/ethereum/tangerine_whistle/__init__.v index ef0fa3436d..f98aa35940 100644 --- a/coq/ethereum/tangerine_whistle/__init__.v +++ b/coq/ethereum/tangerine_whistle/__init__.v @@ -1,3 +1,4 @@ +(* 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 diff --git a/coq/ethereum/tangerine_whistle/blocks.v b/coq/ethereum/tangerine_whistle/blocks.v index a5fd5f862a..0186334e6d 100644 --- a/coq/ethereum/tangerine_whistle/blocks.v +++ b/coq/ethereum/tangerine_whistle/blocks.v @@ -1,3 +1,4 @@ +(* 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 @@ -14,6 +15,6 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. -Require tangerine_whistle.fork_types. -Require tangerine_whistle.transactions. +Require ethereum.crypto.hash. +Require ethereum.tangerine_whistle.fork_types. +Require ethereum.tangerine_whistle.transactions. diff --git a/coq/ethereum/tangerine_whistle/bloom.v b/coq/ethereum/tangerine_whistle/bloom.v index a0903ce0a8..4984ab00e1 100644 --- a/coq/ethereum/tangerine_whistle/bloom.v +++ b/coq/ethereum/tangerine_whistle/bloom.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Logs Bloom ^^^^^^^^^^^^^^^^^^^ @@ -19,10 +20,10 @@ eliminating blocks and receipts from their search. Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require tangerine_whistle.blocks. -Require tangerine_whistle.fork_types. +Require ethereum.tangerine_whistle.blocks. +Require ethereum.tangerine_whistle.fork_types. -Definition add_to_bloom : M unit := +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := (* Add a bloom entry to the bloom filter (`bloom`). @@ -37,13 +38,15 @@ Definition add_to_bloom : M unit := bloom_entry : An entry which is to be added to bloom filter. *) - let* hash := ethereum.crypto.hash.keccak256 (| - bloom_entry - |) in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition logs_bloom : M unit := +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := (* Obtain the logs bloom from a list of log entries. @@ -63,4 +66,4 @@ Definition logs_bloom : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/fork.v b/coq/ethereum/tangerine_whistle/fork.v index 6372706b12..916c252f88 100644 --- a/coq/ethereum/tangerine_whistle/fork.v +++ b/coq/ethereum/tangerine_whistle/fork.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Specification ^^^^^^^^^^^^^^^^^^^^^^ @@ -20,16 +21,18 @@ Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.ethash. Require ethereum.exceptions. -Require tangerine_whistle.blocks. -Require tangerine_whistle.bloom. -Require tangerine_whistle.fork_types. -Require tangerine_whistle.state. -Require tangerine_whistle.transactions. -Require tangerine_whistle.trie. -Require tangerine_whistle.utils.message. -Require tangerine_whistle.vm.interpreter. - -Definition apply_fork : M unit := +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. @@ -49,9 +52,9 @@ Definition apply_fork : M unit := Upgraded block chain object for this hard fork. *) (* TODO statement *) + M.pure tt. - -Definition get_last_256_block_hashes : M unit := +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. @@ -71,22 +74,28 @@ Definition get_last_256_block_hashes : M unit := recent_block_hashes : `List[Hash32]` Hashes of the recent 256 blocks in order of increasing block number. *) - let* recent_blocks := (* TODO expression *) in - (* TODO statement *) - let* recent_block_hashes := (* TODO expression *) in - (* TODO statement *) - let* most_recent_block_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *).["header"] - |) - |) in - do* recent_block_hashes.["append"] (| - most_recent_block_hash - |) in - (* TODO statement *) - - -Definition state_transition : M unit := + 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. @@ -108,41 +117,45 @@ Definition state_transition : M unit := block : Block to apply to `chain`. *) - let* parent_header := (* TODO expression *).["header"] in - do* validate_header (| - block.["header"], - parent_header - |) in - do* validate_ommers (| - block.["ommers"], - block.["header"], + 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 - let* apply_body_output := apply_body (| - chain.["state"], - get_last_256_block_hashes (| - chain - |), - block.["header"].["coinbase"], - block.["header"].["number"], - block.["header"].["gas_limit"], - block.["header"].["timestamp"], - block.["header"].["difficulty"], - block.["transactions"], - block.["ommers"] - |) in + |) ]] 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* chain.["blocks"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| block - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition validate_header : M unit := +Definition validate_header (header : Header) (parent_header : Header) : M unit := (* Verifies a block header. @@ -164,25 +177,29 @@ Definition validate_header : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* block_difficulty := calculate_block_difficulty (| - header.["number"], - header.["timestamp"], - parent_header.["timestamp"], - parent_header.["difficulty"] - |) in + 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 *) - let* block_parent_hash := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - parent_header - |) - |) in + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in (* TODO statement *) - do* validate_proof_of_work (| + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| header - |) in + |) ]] in + M.pure tt. - -Definition generate_header_hash_for_pow : M unit := +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. @@ -205,11 +222,13 @@ Definition generate_header_hash_for_pow : M unit := hash : `Hash32` The PoW valid rlp hash of the passed in header. *) - let* header_data_without_pow_artefacts := (* TODO expression *) in + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition validate_proof_of_work : M unit := +Definition validate_proof_of_work (header : Header) : M unit := (* Validates the Proof of Work constraints. @@ -224,19 +243,25 @@ Definition validate_proof_of_work : M unit := header : Header of interest. *) - let* header_hash := generate_header_hash_for_pow (| - header - |) in - let* cache := ethereum.ethash.generate_cache (| - header.["number"] - |) in + 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 *) - let* limit := (* TODO expression *) in + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in (* TODO statement *) + M.pure tt. - -Definition check_transaction : M unit := +Definition check_transaction (tx : Transaction) (gas_available : Uint) : M Address := (* Check if the transaction is includable in the block. @@ -258,13 +283,15 @@ Definition check_transaction : M unit := If the transaction is not includable. *) (* TODO statement *) - let* sender_address := recover_sender (| - tx - |) in + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + tx + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition make_receipt : M unit := +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. @@ -285,13 +312,15 @@ Definition make_receipt : M unit := receipt : The receipt for the transaction. *) - let* receipt := blocks.Receipt (| + do* M.assign "receipt" [[ + blocks.Receipt ~(| - |) in + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition apply_body : M unit := +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. @@ -330,25 +359,31 @@ Definition apply_body : M unit := apply_body_output : `ApplyBodyOutput` Output of applying the block body to the state. *) - let* gas_available := block_gas_limit in + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - do* pay_rewards (| + do* [[ M.get_local ~(| "pay_rewards" |) ~(| state, block_number, coinbase, ommers - |) in - let* block_gas_used := (* TODO expression *) in - let* block_logs_bloom := bloom.logs_bloom (| - block_logs - |) in - (* TODO statement *) - - -Definition validate_ommers : M unit := + |) ]] 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. @@ -370,23 +405,31 @@ Definition validate_ommers : M unit := chain : History and current state. *) - let* block_hash := rlp.["rlp_hash"] (| - block_header - |) in + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* ommers_hashes := (* TODO expression *) in + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* recent_canonical_blocks := (* TODO expression *) in - let* recent_canonical_block_hashes := (* TODO expression *) in + 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 : M unit := +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. @@ -412,21 +455,25 @@ Definition pay_rewards : M unit := ommers : List of ommers mentioned in the current block. *) - let* ommer_count := ethereum_types.numeric.U256 (| - len (| - ommers - |) - |) in - let* miner_reward := (* TODO expression *) in - do* state.create_ether (| + 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, - miner_reward - |) in + M.get_local ~(| "miner_reward" |) + |) ]] in (* TODO statement *) + M.pure tt. - -Definition process_transaction : M unit := +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := (* Execute a transaction against the provided environment. @@ -454,67 +501,95 @@ Definition process_transaction : M unit := Logs generated during execution. *) (* TODO statement *) - let* sender := env.["origin"] in - let* sender_account := state.get_account (| - env.["state"], - sender - |) in - let* gas_fee := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - let* gas := (* TODO expression *) in - do* state.increment_nonce (| - env.["state"], - sender - |) in - let* sender_balance_after_gas_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - ethereum_types.numeric.U256 (| - sender_balance_after_gas_fee + 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 - let* message := utils.message.prepare_message (| - sender, - tx.["to"], - tx.["value"], - tx.["data"], - gas, - env - |) in - let* output := vm.interpreter.process_message_call (| - message, - env - |) in - let* gas_used := (* TODO expression *) in - let* gas_refund := min (| - (* TODO expression *), - ethereum_types.numeric.Uint (| - output.["refund_counter"] - |) - |) in - let* gas_refund_amount := (* TODO expression *) in - let* transaction_fee := (* TODO expression *) in - let* total_gas_used := (* TODO expression *) in - let* sender_balance_after_refund := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - sender, - sender_balance_after_refund - |) in - let* coinbase_balance_after_mining_fee := (* TODO expression *) in - do* state.set_account_balance (| - env.["state"], - env.["coinbase"], - coinbase_balance_after_mining_fee - |) in - (* TODO statement *) - (* TODO statement *) - - -Definition validate_transaction : M unit := + |) ]] 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. @@ -542,9 +617,9 @@ Definition validate_transaction : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition calculate_intrinsic_cost : M unit := +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := (* Calculates the gas that is charged before execution is started. @@ -567,13 +642,15 @@ Definition calculate_intrinsic_cost : M unit := verified : `ethereum.base_types.Uint` The intrinsic cost of the transaction. *) - let* data_cost := (* TODO expression *) in + do* M.assign "data_cost" [[ + 0 in + ]] in (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition recover_sender : M unit := +Definition recover_sender (tx : Transaction) : M Address := (* Extracts the sender address from a transaction. @@ -597,18 +674,20 @@ Definition recover_sender : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) - let* public_key := ethereum.crypto.elliptic_curve.secp256k1_recover (| - r, - s, - (* TODO expression *), - signing_hash (| - tx - |) - |) in + 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 : M unit := +Definition signing_hash (tx : Transaction) : M Hash32 := (* Compute the hash of a transaction used in the signature. @@ -627,9 +706,9 @@ Definition signing_hash : M unit := Hash of the transaction. *) (* TODO statement *) + M.pure tt. - -Definition compute_header_hash : M unit := +Definition compute_header_hash (header : Header) : M Hash32 := (* Computes the hash of a block header. @@ -662,9 +741,9 @@ Definition compute_header_hash : M unit := Hash of the header. *) (* TODO statement *) + M.pure tt. - -Definition check_gas_limit : M unit := +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := (* Validates the gas limit for a block. @@ -692,14 +771,16 @@ Definition check_gas_limit : M unit := check : `bool` True if gas limit constraints are satisfied, False otherwise. *) - let* max_adjustment_delta := (* TODO expression *) in + 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 : M unit := +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. @@ -736,9 +817,15 @@ Definition calculate_block_difficulty : M unit := difficulty : `ethereum.base_types.Uint` Computed difficulty for a block. *) - let* offset := (* TODO expression *) in - let* difficulty := (* TODO expression *) in - let* num_bomb_periods := (* TODO expression *) in - (* TODO statement *) - (* TODO statement *) - + 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.v b/coq/ethereum/tangerine_whistle/fork_types.v index 14de99d5e5..d84cffdf45 100644 --- a/coq/ethereum/tangerine_whistle/fork_types.v +++ b/coq/ethereum/tangerine_whistle/fork_types.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Types ^^^^^^^^^^^^^^ @@ -16,9 +17,10 @@ Require dataclasses. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require ..crypto.hash. +Require ethereum.__init__. +Require ethereum.crypto.hash. -Definition encode_account : M unit := +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := (* Encode `Account` dataclass. @@ -26,4 +28,4 @@ Definition encode_account : M unit := encoded without providing a storage root. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/state.v b/coq/ethereum/tangerine_whistle/state.v index ab82e8b22f..7e913e3666 100644 --- a/coq/ethereum/tangerine_whistle/state.v +++ b/coq/ethereum/tangerine_whistle/state.v @@ -1,3 +1,4 @@ +(* Generated *) (* State ^^^^^ @@ -22,10 +23,10 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require tangerine_whistle.fork_types. -Require tangerine_whistle.trie. +Require ethereum.tangerine_whistle.fork_types. +Require ethereum.tangerine_whistle.trie. -Definition close_state : M unit := +Definition close_state (state : State) : M unit := (* Free resources held by the state. Used by optimized implementations to release file descriptors. @@ -33,9 +34,9 @@ Definition close_state : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition begin_transaction : M unit := +Definition begin_transaction (state : State) : M unit := (* Start a state transaction. @@ -47,12 +48,12 @@ Definition begin_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["append"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition commit_transaction : M unit := +Definition commit_transaction (state : State) : M unit := (* Commit a state transaction. @@ -61,12 +62,12 @@ Definition commit_transaction : M unit := state : State The state. *) - do* state.["_snapshots"].["pop"] (| + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| - |) in + |) ]] in + M.pure tt. - -Definition rollback_transaction : M unit := +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. @@ -77,9 +78,9 @@ Definition rollback_transaction : M unit := The state. *) (* TODO assignment *) + M.pure tt. - -Definition get_account : M unit := +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. @@ -99,14 +100,16 @@ Definition get_account : M unit := account : `Account` Account at address. *) - let* account := get_account_optional (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition get_account_optional : M unit := +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. @@ -123,14 +126,16 @@ Definition get_account_optional : M unit := account : `Account` Account at address. *) - let* account := trie.trie_get (| - state.["_main_trie"], - address - |) in + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition set_account : M unit := +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()`). @@ -144,14 +149,14 @@ Definition set_account : M unit := account : `Account` Account to set at address. *) - do* trie.trie_set (| - state.["_main_trie"], + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), address, account - |) in - + |) ]] in + M.pure tt. -Definition destroy_account : M unit := +Definition destroy_account (state : State) (address : Address) : M unit := (* Completely remove the account at `address` and all of its storage. @@ -166,18 +171,18 @@ Definition destroy_account : M unit := address : `Address` Address of account to destroy. *) - do* destroy_storage (| + do* [[ M.get_local ~(| "destroy_storage" |) ~(| state, address - |) in - do* set_account (| + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - (* TODO expression *) - |) in - + tt + |) ]] in + M.pure tt. -Definition destroy_storage : M unit := +Definition destroy_storage (state : State) (address : Address) : M unit := (* Completely remove the storage at `address`. @@ -189,9 +194,9 @@ Definition destroy_storage : M unit := Address of account whose storage is to be deleted. *) (* TODO statement *) + M.pure tt. - -Definition get_storage : M unit := +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. @@ -210,19 +215,23 @@ Definition get_storage : M unit := value : `U256` Value at the key. *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - let* value := trie.trie_get (| - trie, - key - |) in + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition set_storage : M unit := +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. @@ -239,19 +248,21 @@ Definition set_storage : M unit := Value to set at the key. *) (* TODO statement *) - let* trie := state.["_storage_tries"].["get"] (| - address - |) in + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in (* TODO statement *) - do* trie.trie_set (| - trie, + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), key, value - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition storage_root : M unit := +Definition storage_root (state : State) (address : Address) : M Root := (* Calculate the storage root of an account. @@ -269,9 +280,9 @@ Definition storage_root : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition state_root : M unit := +Definition state_root (state : State) : M Root := (* Calculate the state root. @@ -288,9 +299,9 @@ Definition state_root : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition account_exists : M unit := +Definition account_exists (state : State) (address : Address) : M bool := (* Checks if an account exists in the state trie @@ -307,9 +318,9 @@ Definition account_exists : M unit := True if account exists in the state trie, False otherwise *) (* TODO statement *) + M.pure tt. - -Definition account_has_code_or_nonce : M unit := +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := (* Checks if an account has non zero nonce or non empty code @@ -326,49 +337,51 @@ Definition account_has_code_or_nonce : M unit := True if if an account has non zero nonce or non empty code, False otherwise. *) - let* account := get_account (| - state, - address - |) in + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in (* TODO statement *) + M.pure tt. - -Definition modify_state : M unit := +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := (* Modify an `Account` in the `State`. *) - do* set_account (| + do* [[ M.get_local ~(| "set_account" |) ~(| state, address, - ethereum_types.frozen.modify (| - get_account (| + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| state, address |), f |) - |) in + |) ]] in + M.pure tt. - -Definition move_ether : M unit := +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := (* Move funds between accounts. *) (* TODO statement *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, sender_address, - reduce_sender_balance - |) in - do* modify_state (| + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| state, recipient_address, - increase_recipient_balance - |) in - + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. -Definition set_account_balance : M unit := +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := (* Sets the balance of an account. @@ -384,14 +397,14 @@ Definition set_account_balance : M unit := The amount that needs to set in balance. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - set_balance - |) in + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. - -Definition touch_account : M unit := +Definition touch_account (state : State) (address : Address) : M unit := (* Initializes an account to state. @@ -404,9 +417,9 @@ Definition touch_account : M unit := The address of the account that need to initialised. *) (* TODO statement *) + M.pure tt. - -Definition increment_nonce : M unit := +Definition increment_nonce (state : State) (address : Address) : M unit := (* Increments the nonce of an account. @@ -419,14 +432,14 @@ Definition increment_nonce : M unit := Address of the account whose nonce needs to be incremented. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_nonce - |) in + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. - -Definition set_code : M unit := +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := (* Sets Account code. @@ -442,14 +455,14 @@ Definition set_code : M unit := The bytecode that needs to be set. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - write_code - |) in - + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. -Definition create_ether : M unit := +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := (* Add newly created ether to an account. @@ -463,9 +476,9 @@ Definition create_ether : M unit := The amount of ether to be added to the account of interest. *) (* TODO statement *) - do* modify_state (| + do* [[ M.get_local ~(| "modify_state" |) ~(| state, address, - increase_balance - |) in - + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/transactions.v b/coq/ethereum/tangerine_whistle/transactions.v index 4458fc223d..2545cb2dd1 100644 --- a/coq/ethereum/tangerine_whistle/transactions.v +++ b/coq/ethereum/tangerine_whistle/transactions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Transactions are atomic units of work created externally to Ethereum and submitted to be executed. If Ethereum is viewed as a state machine, @@ -9,4 +10,4 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.frozen. Require ethereum_types.numeric. -Require tangerine_whistle.fork_types. +Require ethereum.tangerine_whistle.fork_types. diff --git a/coq/ethereum/tangerine_whistle/trie.v b/coq/ethereum/tangerine_whistle/trie.v index 5f0ab29642..3b45315972 100644 --- a/coq/ethereum/tangerine_whistle/trie.v +++ b/coq/ethereum/tangerine_whistle/trie.v @@ -1,3 +1,4 @@ +(* Generated *) (* State Trie ^^^^^^^^^^ @@ -14,7 +15,7 @@ The state trie is the structure responsible for storing *) -Definition encode_internal_node : M unit := +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 @@ -35,22 +36,24 @@ Definition encode_internal_node : M unit := *) (* TODO statement *) (* TODO statement *) - let* encoded := rlp.["encode"] (| - unencoded - |) in + 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 : M unit := +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 : M unit := +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. @@ -66,9 +69,9 @@ Definition copy_trie : M unit := A copy of the trie. *) (* TODO statement *) + M.pure tt. - -Definition trie_set : M unit := +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := (* Stores an item in a Merkle Trie. @@ -85,9 +88,9 @@ Definition trie_set : M unit := Node to insert at `key`. *) (* TODO statement *) + M.pure tt. - -Definition trie_get : M unit := +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := (* Gets an item from the Merkle Trie. @@ -106,17 +109,17 @@ Definition trie_get : M unit := Node at `key` in the trie. *) (* TODO statement *) + M.pure tt. - -Definition common_prefix_length : M unit := +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 : M unit := +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := (* Compresses nibble-list into a standard byte array with a flag. @@ -150,14 +153,16 @@ Definition nibble_list_to_compact : M unit := compressed : `bytearray` Compact byte array. *) - let* compact := bytearray (| + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| - |) in + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition bytes_to_nibble_list : M unit := +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := (* Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). @@ -171,14 +176,16 @@ Definition bytes_to_nibble_list : M unit := nibble_list : `Bytes` The `Bytes` in nibble-list format. *) - let* nibble_list := bytearray (| - (* TODO expression *) - |) in + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition _prepare_trie : M unit := +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. @@ -199,9 +206,9 @@ Definition _prepare_trie : M unit := (* TODO statement *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition root : M unit := +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := (* Computes the root of a modified merkle patricia trie (MPT). @@ -219,22 +226,26 @@ Definition root : M unit := root : `.fork_types.Root` MPT root of the underlying key-value pairs. *) - let* obj := _prepare_trie (| - trie, - get_storage_root - |) in - let* root_node := encode_internal_node (| - patricialize (| - obj, - Uint (| - (* TODO expression *) + 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 + ]] in (* TODO statement *) + M.pure tt. - -Definition patricialize : M unit := +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := (* Structural composition function. @@ -254,21 +265,29 @@ Definition patricialize : M unit := Root node of `obj`. *) (* TODO statement *) - let* arbitrary_key := next (| - iter (| - obj - |) - |) in + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in (* TODO statement *) - let* substring := (* TODO expression *) in - let* prefix_length := len (| - substring - |) in + 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 *) - let* value := (* TODO expression *) in + do* M.assign "value" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/utils/__init__.v b/coq/ethereum/tangerine_whistle/utils/__init__.v index beff4482b1..7f30fe939b 100644 --- a/coq/ethereum/tangerine_whistle/utils/__init__.v +++ b/coq/ethereum/tangerine_whistle/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions unique to this particular fork. *) diff --git a/coq/ethereum/tangerine_whistle/utils/address.v b/coq/ethereum/tangerine_whistle/utils/address.v index e20ee01fa7..ec6712c185 100644 --- a/coq/ethereum/tangerine_whistle/utils/address.v +++ b/coq/ethereum/tangerine_whistle/utils/address.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,9 +18,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require tangerine_whistle.fork_types. +Require ethereum.__init__. +Require ethereum.tangerine_whistle.fork_types. -Definition to_address : M unit := +Definition to_address (data : (* TODO type *)) : M Address := (* Convert a Uint or U256 value to a valid address (20 bytes). @@ -34,9 +36,9 @@ Definition to_address : M unit := The obtained address. *) (* TODO statement *) + M.pure tt. - -Definition compute_contract_address : M unit := +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := (* Computes address of the new account that needs to be created. @@ -53,15 +55,21 @@ Definition compute_contract_address : M unit := address: `ethereum.tangerine_whistle.fork_types.Address` The computed address of the new account. *) - let* computed_address := ethereum.crypto.hash.keccak256 (| - rlp.["encode"] (| - (* TODO expression *) - |) - |) in - let* canonical_address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - canonical_address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/tangerine_whistle/utils/hexadecimal.v index b3ef61f1c6..ba90513cd1 100644 --- a/coq/ethereum/tangerine_whistle/utils/hexadecimal.v +++ b/coq/ethereum/tangerine_whistle/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Tangerine Whistle types. *) Require ethereum.utils.hexadecimal. -Require tangerine_whistle.fork_types. +Require ethereum.tangerine_whistle.fork_types. -Definition hex_to_root : M unit := +Definition hex_to_root (hex_string : str) : M Root := (* Convert hex string to trie root. @@ -31,9 +32,9 @@ Definition hex_to_root : M unit := Trie root obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bloom : M unit := +Definition hex_to_bloom (hex_string : str) : M Bloom := (* Convert hex string to bloom. @@ -48,9 +49,9 @@ Definition hex_to_bloom : M unit := Bloom obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_address : M unit := +Definition hex_to_address (hex_string : str) : M Address := (* Convert hex string to Address (20 bytes). @@ -65,4 +66,4 @@ Definition hex_to_address : M unit := The address obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/utils/message.v b/coq/ethereum/tangerine_whistle/utils/message.v index c0aeaa4554..1e447e6a61 100644 --- a/coq/ethereum/tangerine_whistle/utils/message.v +++ b/coq/ethereum/tangerine_whistle/utils/message.v @@ -1,3 +1,4 @@ +(* Generated *) (* Hardfork Utility Functions For The Message Data-structure ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,12 +17,12 @@ specification. Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require tangerine_whistle.fork_types. -Require tangerine_whistle.state. -Require tangerine_whistle.vm. -Require tangerine_whistle.utils.address. +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 : M unit := +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. @@ -53,4 +54,4 @@ Definition prepare_message : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/__init__.v b/coq/ethereum/tangerine_whistle/vm/__init__.v index d53025e199..39d1dc8d15 100644 --- a/coq/ethereum/tangerine_whistle/vm/__init__.v +++ b/coq/ethereum/tangerine_whistle/vm/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,11 +19,11 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Require tangerine_whistle.blocks. -Require tangerine_whistle.fork_types. -Require tangerine_whistle.state. +Require ethereum.tangerine_whistle.blocks. +Require ethereum.tangerine_whistle.fork_types. +Require ethereum.tangerine_whistle.state. -Definition incorporate_child_on_success : M unit := +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of a successful `child_evm` into the parent `evm`. @@ -33,15 +34,21 @@ Definition incorporate_child_on_success : M unit := child_evm : The child evm to incorporate. *) - (* TODO statement *) - (* TODO statement *) - (* TODO statement *) - do* evm.["accounts_to_delete"].["update"] (| - child_evm.["accounts_to_delete"] - |) in + 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 : M unit := +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := (* Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. @@ -52,5 +59,7 @@ Definition incorporate_child_on_error : M unit := child_evm : The child evm to incorporate. *) - (* 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/tangerine_whistle/vm/exceptions.v b/coq/ethereum/tangerine_whistle/vm/exceptions.v index 1784494410..47e26555d5 100644 --- a/coq/ethereum/tangerine_whistle/vm/exceptions.v +++ b/coq/ethereum/tangerine_whistle/vm/exceptions.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Exceptions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/tangerine_whistle/vm/gas.v b/coq/ethereum/tangerine_whistle/vm/gas.v index 5b97f89352..4708b4166b 100644 --- a/coq/ethereum/tangerine_whistle/vm/gas.v +++ b/coq/ethereum/tangerine_whistle/vm/gas.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Gas ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,9 +18,10 @@ Require typing. Require ethereum_types.numeric. Require ethereum.trace. Require ethereum.utils.numeric. -Require tangerine_whistle.vm.exceptions. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.exceptions. -Definition charge_gas : M unit := +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := (* Subtracts `amount` from `evm.gas_left`. @@ -31,18 +33,18 @@ Definition charge_gas : M unit := The amount of gas the current operation requires. *) - do* ethereum.trace.evm_trace (| + do* [[ ethereum.trace.evm_trace ~(| evm, - ethereum.trace.GasAndRefund (| - int (| + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| amount |) |) - |) in + |) ]] in (* TODO statement *) + M.pure tt. - -Definition calculate_memory_gas_cost : M unit := +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, @@ -58,14 +60,22 @@ Definition calculate_memory_gas_cost : M unit := total_gas_cost : `ethereum.base_types.Uint` The gas cost for storing data in memory. *) - let* size_in_words := (* TODO expression *) in - let* linear_cost := (* TODO expression *) in - let* quadratic_cost := (* TODO expression *) in - let* total_gas_cost := (* TODO expression *) in + 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 : M unit := +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := (* Calculates the gas amount to extend memory @@ -81,22 +91,28 @@ Definition calculate_gas_extend_memory : M unit := ------- extend_memory: `ExtendMemory` *) - let* size_to_extend := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* to_be_paid := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* current_size := ethereum_types.numeric.Uint (| - len (| - memory - |) - |) in + 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 : M unit := +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. @@ -122,18 +138,22 @@ Definition calculate_message_call_gas : M unit := ------- message_call_gas: `MessageCallGas` *) - let* call_stipend := (* TODO expression *) in + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - let* gas := min (| - gas, - max_message_call_gas (| - (* TODO expression *) - |) - |) in + 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 : M unit := +Definition max_message_call_gas (gas : Uint) : M Uint := (* Calculates the maximum gas that is allowed for making a message call @@ -148,4 +168,4 @@ Definition max_message_call_gas : M unit := The maximum gas allowed for making the message-call. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/__init__.v b/coq/ethereum/tangerine_whistle/vm/instructions/__init__.v index b36b1ebfef..cbd7e7e63a 100644 --- a/coq/ethereum/tangerine_whistle/vm/instructions/__init__.v +++ b/coq/ethereum/tangerine_whistle/vm/instructions/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* EVM Instruction Encoding (Opcodes) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/arithmetic.v b/coq/ethereum/tangerine_whistle/vm/instructions/arithmetic.v index fae846724f..52e6b6b24e 100644 --- a/coq/ethereum/tangerine_whistle/vm/instructions/arithmetic.v +++ b/coq/ethereum/tangerine_whistle/vm/instructions/arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Arithmetic Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,11 @@ Implementations of the EVM Arithmetic instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require tangerine_whistle.vm.gas. -Require tangerine_whistle.vm.stack. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.stack. -Definition add : M unit := +Definition add (evm : Evm) : M unit := (* Adds the top two elements of the stack together, and pushes the result back on the stack. @@ -28,27 +30,37 @@ Definition add : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_add"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sub (evm : Evm) : M unit := (* Subtracts the top two elements of the stack, and pushes the result back on the stack. @@ -59,27 +71,37 @@ Definition sub : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_sub"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mul (evm : Evm) : M unit := (* Multiply the top two elements of the stack, and pushes the result back on the stack. @@ -90,27 +112,37 @@ Definition mul : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := x.["wrapping_mul"] (| - y - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition div (evm : Evm) : M unit := (* Integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -121,25 +153,33 @@ Definition div : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |) in - let* divisor := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - quotient - |) 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 : M unit := +Definition sdiv (evm : Evm) : M unit := (* Signed integer division of the top two elements of the stack. Pushes the result back on the stack. @@ -150,31 +190,39 @@ Definition sdiv : M unit := The current EVM frame. *) - let* dividend := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* divisor := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - quotient + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition mod : M unit := +Definition mod (evm : Evm) : M unit := (* Modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -185,25 +233,33 @@ Definition mod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - remainder - |) in + |) ]] 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 : M unit := +Definition smod (evm : Evm) : M unit := (* Signed modulo remainder of the top two elements of the stack. Pushes the result back on the stack. @@ -214,31 +270,39 @@ Definition smod : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* y := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_signed"] (| - remainder + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition addmod : M unit := +Definition addmod (evm : Evm) : M unit := (* Modulo addition of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -249,34 +313,44 @@ Definition addmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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 : M unit := +Definition mulmod (evm : Evm) : M unit := (* Modulo multiplication of the top 2 elements with the 3rd element. Pushes the result back on the stack. @@ -287,34 +361,44 @@ Definition mulmod : M unit := The current EVM frame. *) - let* x := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* y := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* z := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - result - |) 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 : M unit := +Definition exp (evm : Evm) : M unit := (* Exponential operation of the top 2 elements. Pushes the result back on the stack. @@ -325,39 +409,53 @@ Definition exp : M unit := The current EVM frame. *) - let* base := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* exponent_bits := exponent.["bit_length"] (| - - |) in - let* exponent_bytes := (* TODO expression *) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - pow (| - base, - exponent, - (* 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 - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + ]] in + M.pure tt. -Definition signextend : M unit := +Definition signextend (evm : Evm) : M unit := (* Sign extend operation. In other words, extend a signed number which fits in N bytes to 32 bytes. @@ -368,20 +466,28 @@ Definition signextend : M unit := The current EVM frame. *) - let* byte_num := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/tangerine_whistle/vm/instructions/bitwise.v index b68bd75bbe..45716bf9c9 100644 --- a/coq/ethereum/tangerine_whistle/vm/instructions/bitwise.v +++ b/coq/ethereum/tangerine_whistle/vm/instructions/bitwise.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Bitwise Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM bitwise instructions. *) Require ethereum_types.numeric. -Require tangerine_whistle.vm.gas. -Require tangerine_whistle.vm.stack. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.stack. -Definition bitwise_and : M unit := +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. @@ -27,24 +29,32 @@ Definition bitwise_and : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_or : M unit := + |) ]] 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. @@ -55,24 +65,32 @@ Definition bitwise_or : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_xor : M unit := + |) ]] 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. @@ -83,24 +101,32 @@ Definition bitwise_xor : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - let* y := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition bitwise_not : M unit := + |) ]] 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. @@ -111,21 +137,27 @@ Definition bitwise_not : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), (* TODO expression *) - |) in - (* TODO statement *) - - -Definition get_byte : M unit := + |) ]] 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 @@ -137,20 +169,28 @@ Definition get_byte : M unit := The current EVM frame. *) - let* byte_index := stack.pop (| - evm.["stack"] - |) in - let* word := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 (| - evm.["stack"], - result - |) in + |) ]] 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.v b/coq/ethereum/tangerine_whistle/vm/instructions/block.v index 0d927d3693..f28248f8ab 100644 --- a/coq/ethereum/tangerine_whistle/vm/instructions/block.v +++ b/coq/ethereum/tangerine_whistle/vm/instructions/block.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Block Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM block instructions. *) Require ethereum_types.numeric. -Require tangerine_whistle.vm.gas. -Require tangerine_whistle.vm.stack. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.stack. -Definition block_hash : M unit := +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. @@ -27,27 +29,35 @@ Definition block_hash : M unit := The current EVM frame. *) - let* block_number := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* max_block_number := (* TODO expression *) in + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in (* TODO statement *) - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition coinbase : M unit := +Definition coinbase (evm : Evm) : M unit := (* Push the current block's beneficiary address (address of the block miner) onto the stack. @@ -62,20 +72,24 @@ Definition coinbase : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["coinbase"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition timestamp : M unit := +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. @@ -90,18 +104,22 @@ Definition timestamp : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["env"].["time"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition number (evm : Evm) : M unit := (* Push the current block's number onto the stack. @@ -115,20 +133,24 @@ Definition number : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["number"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition difficulty : M unit := +Definition difficulty (evm : Evm) : M unit := (* Push the current block's difficulty onto the stack. @@ -142,20 +164,24 @@ Definition difficulty : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["difficulty"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_limit : M unit := +Definition gas_limit (evm : Evm) : M unit := (* Push the current block's gas limit onto the stack. @@ -169,15 +195,19 @@ Definition gas_limit : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_limit"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/tangerine_whistle/vm/instructions/comparison.v index d813938264..1a7b865f20 100644 --- a/coq/ethereum/tangerine_whistle/vm/instructions/comparison.v +++ b/coq/ethereum/tangerine_whistle/vm/instructions/comparison.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Comparison Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,10 +14,11 @@ Implementations of the EVM Comparison instructions. *) Require ethereum_types.numeric. -Require tangerine_whistle.vm.gas. -Require tangerine_whistle.vm.stack. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.stack. -Definition less_than : M unit := +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. @@ -27,27 +29,37 @@ Definition less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_less_than : M unit := + |) ]] 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. @@ -57,31 +69,41 @@ Definition signed_less_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition greater_than : M unit := + |) ]] 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. @@ -92,27 +114,37 @@ Definition greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition signed_greater_than : M unit := + |) ]] 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. @@ -122,31 +154,41 @@ Definition signed_greater_than : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - let* right := stack.pop (| - evm.["stack"] - |).["to_signed"] (| - - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition equal : M unit := + |) ]] 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. @@ -157,27 +199,37 @@ Definition equal : M unit := The current EVM frame. *) - let* left := stack.pop (| - evm.["stack"] - |) in - let* right := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + 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 - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - - -Definition is_zero : M unit := + |) ]] 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. @@ -188,19 +240,27 @@ Definition is_zero : M unit := The current EVM frame. *) - let* x := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* result := ethereum_types.numeric.U256 (| - (* TODO expression *) - |) in - do* stack.push (| - evm.["stack"], - result - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/tangerine_whistle/vm/instructions/control_flow.v index 2187e73a8c..5cd448277e 100644 --- a/coq/ethereum/tangerine_whistle/vm/instructions/control_flow.v +++ b/coq/ethereum/tangerine_whistle/vm/instructions/control_flow.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Control Flow Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM control flow instructions. *) Require ethereum_types.numeric. -Require tangerine_whistle.vm.gas. -Require tangerine_whistle.vm.exceptions. -Require tangerine_whistle.vm.stack. +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 : M unit := +Definition stop (evm : Evm) : M unit := (* Stop further execution of EVM code. @@ -29,10 +31,14 @@ Definition stop : M unit := (* TODO statement *) (* TODO statement *) (* TODO assignment *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jump : M unit := +Definition jump (evm : Evm) : M unit := (* Alter the program counter to the location specified by the top of the stack. @@ -43,20 +49,22 @@ Definition jump : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition jumpi : M unit := +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 @@ -68,23 +76,27 @@ Definition jumpi : M unit := The current EVM frame. *) - let* jump_dest := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* conditional_value := stack.pop (| - evm.["stack"] - |) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO statement *) (* TODO assignment *) + M.pure tt. - -Definition pc : M unit := +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. @@ -96,20 +108,24 @@ Definition pc : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["pc"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition gas_left : M unit := +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. @@ -121,20 +137,24 @@ Definition gas_left : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["gas_left"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition jumpdest : M unit := +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 @@ -147,10 +167,14 @@ Definition jumpdest : M unit := *) (* TODO statement *) - do* vm.gas.charge_gas (| + do* [[ vm.gas.charge_gas ~(| evm, vm.gas.GAS_JUMPDEST - |) in - (* TODO statement *) + |) ]] 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.v b/coq/ethereum/tangerine_whistle/vm/instructions/environment.v index 382a382b7b..0ecd2769c2 100644 --- a/coq/ethereum/tangerine_whistle/vm/instructions/environment.v +++ b/coq/ethereum/tangerine_whistle/vm/instructions/environment.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Environmental Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,13 +15,14 @@ Implementations of the EVM environment related instructions. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require tangerine_whistle.state. -Require tangerine_whistle.utils.address. -Require tangerine_whistle.vm.memory. -Require tangerine_whistle.vm.gas. -Require tangerine_whistle.vm.stack. - -Definition address : M unit := +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. @@ -31,20 +33,24 @@ Definition address : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["current_target"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition balance : M unit := +Definition balance (evm : Evm) : M unit := (* Pushes the balance of the given account onto the stack. @@ -54,27 +60,35 @@ Definition balance : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* balance := state.get_account (| - evm.["env"].["state"], - address - |).["balance"] in - do* stack.push (| - evm.["stack"], - balance - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +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. @@ -86,20 +100,24 @@ Definition origin : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["env"].["origin"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition caller : M unit := +Definition caller (evm : Evm) : M unit := (* Pushes the address of the caller onto the stack. @@ -110,20 +128,24 @@ Definition caller : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - evm.["message"].["caller"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition callvalue : M unit := +Definition callvalue (evm : Evm) : M unit := (* Push the value (in wei) sent with the call onto the stack. @@ -134,18 +156,22 @@ Definition callvalue : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - evm.["message"].["value"] - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition calldataload (evm : Evm) : M unit := (* Push a word (32 bytes) of the input data belonging to the current environment onto the stack. @@ -156,30 +182,38 @@ Definition calldataload : M unit := The current EVM frame. *) - let* start_index := stack.pop (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - start_index, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] 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* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - value + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 |) - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition calldatasize : M unit := +Definition calldatasize (evm : Evm) : M unit := (* Push the size of input data in current environment onto the stack. @@ -190,22 +224,26 @@ Definition calldatasize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["message"].["data"] + |) ]] 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 - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition calldatacopy : M unit := +Definition calldatacopy (evm : Evm) : M unit := (* Copy a portion of the input data in current environment to memory. @@ -218,40 +256,60 @@ Definition calldatacopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* data_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["message"].["data"], - data_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition codesize (evm : Evm) : M unit := (* Push the size of code running in current environment onto the stack. @@ -262,22 +320,26 @@ Definition codesize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["code"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition codecopy : M unit := +Definition codecopy (evm : Evm) : M unit := (* Copy a portion of the code in current environment to memory. @@ -290,40 +352,60 @@ Definition codecopy : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := vm.memory.buffer_read (| - evm.["code"], - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition gasprice (evm : Evm) : M unit := (* Push the gas price used in current environment onto the stack. @@ -334,20 +416,24 @@ Definition gasprice : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - evm.["env"].["gas_price"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) |) - |) in - (* TODO statement *) - + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition extcodesize : M unit := +Definition extcodesize (evm : Evm) : M unit := (* Push the code size of a given account onto the stack. @@ -357,31 +443,39 @@ Definition extcodesize : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - do* gas.charge_gas (| + 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 - let* codesize := ethereum_types.numeric.U256 (| - len (| - state.get_account (| - evm.["env"].["state"], - address - |).["code"] + |) ]] 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 - do* stack.push (| - evm.["stack"], - codesize - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition extcodecopy : M unit := +Definition extcodecopy (evm : Evm) : M unit := (* Copy a portion of an account's code to memory. @@ -391,44 +485,68 @@ Definition extcodecopy : M unit := The current EVM frame. *) - let* address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* code_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* copy_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* code := state.get_account (| - evm.["env"].["state"], - address - |).["code"] in - let* value := vm.memory.buffer_read (| - code, - code_start_index, - size - |) in - do* vm.memory.memory_write (| - evm.["memory"], - memory_start_index, - value - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/tangerine_whistle/vm/instructions/keccak.v index 7e9a06cdea..d2da5e97bf 100644 --- a/coq/ethereum/tangerine_whistle/vm/instructions/keccak.v +++ b/coq/ethereum/tangerine_whistle/vm/instructions/keccak.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Keccak Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,11 +16,12 @@ Implementations of the EVM keccak instructions. Require ethereum_types.numeric. Require ethereum.crypto.hash. Require ethereum.utils.numeric. -Require tangerine_whistle.vm.gas. -Require tangerine_whistle.vm.memory. -Require tangerine_whistle.vm.stack. +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 : M unit := +Definition keccak (evm : Evm) : M unit := (* Pushes to the stack the Keccak-256 hash of a region of memory. @@ -32,36 +34,56 @@ Definition keccak : M unit := The current EVM frame. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* words := (* TODO expression *) in - let* word_gas_cost := (* TODO expression *) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* data := memory.memory_read_bytes (| - evm.["memory"], - memory_start_index, - size - |) in - let* hash := ethereum.crypto.hash.keccak256 (| - data - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256.["from_be_bytes"] (| - hash + |) ]] 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 - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/tangerine_whistle/vm/instructions/log.v index 358dc7cedf..11d0131f08 100644 --- a/coq/ethereum/tangerine_whistle/vm/instructions/log.v +++ b/coq/ethereum/tangerine_whistle/vm/instructions/log.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Logging Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,12 +15,13 @@ Implementations of the EVM logging instructions. Require functools. Require ethereum_types.numeric. -Require tangerine_whistle.blocks. -Require tangerine_whistle.vm.gas. -Require tangerine_whistle.vm.memory. -Require tangerine_whistle.vm.stack. +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 : M unit := +Definition log_n (evm : Evm) (num_topics : U256) : M unit := (* Appends a log entry, having `num_topics` topics, to the evm logs. @@ -34,26 +36,42 @@ Definition log_n : M unit := The number of topics to be included in the log entry. *) - let* memory_start_index := stack.pop (| - evm.["stack"] - |) in - let* size := stack.pop (| - evm.["stack"] - |) in - let* topics := (* TODO expression *) in + 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 *) - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 *) - let* log_entry := blocks.Log (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "log_entry" [[ + blocks.Log ~(| - |) in + |) in + ]] in (* TODO assignment *) - (* 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/memory.v b/coq/ethereum/tangerine_whistle/vm/instructions/memory.v index 5b7c96f8f5..483c212366 100644 --- a/coq/ethereum/tangerine_whistle/vm/instructions/memory.v +++ b/coq/ethereum/tangerine_whistle/vm/instructions/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM Memory instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require tangerine_whistle.vm.gas. -Require tangerine_whistle.vm.memory. -Require tangerine_whistle.vm.stack. +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 : M unit := +Definition mstore (evm : Evm) : M unit := (* Stores a word to memory. This also expands the memory, if the memory is @@ -30,32 +32,44 @@ Definition mstore : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| - - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - do* memory.memory_write (| - evm.["memory"], - start_position, - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition mstore8 (evm : Evm) : M unit := (* Stores a byte to memory. This also expands the memory, if the memory is @@ -67,33 +81,47 @@ Definition mstore8 : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* normalized_bytes_value := ethereum_types.bytes.Bytes (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ (* TODO expression *) - |) in - do* memory.memory_write (| - evm.["memory"], - start_position, - normalized_bytes_value - |) in - (* TODO statement *) - + ]] 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 : M unit := +Definition mload (evm : Evm) : M unit := (* Load word from memory. @@ -103,35 +131,47 @@ Definition mload : M unit := The current EVM frame. *) - let* start_position := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* value := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.memory_read_bytes (| - evm.["memory"], - start_position, - ethereum_types.numeric.U256 (| - (* 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 - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) + ]] in + M.pure tt. - -Definition msize : M unit := +Definition msize (evm : Evm) : M unit := (* Push the size of active memory in bytes onto the stack. @@ -142,17 +182,21 @@ Definition msize : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in - do* stack.push (| - evm.["stack"], - ethereum_types.numeric.U256 (| - len (| - evm.["memory"] + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) |) |) - |) in - (* TODO statement *) - + |) ]] 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.v b/coq/ethereum/tangerine_whistle/vm/instructions/stack.v index d8caa6a1e1..5d773992f7 100644 --- a/coq/ethereum/tangerine_whistle/vm/instructions/stack.v +++ b/coq/ethereum/tangerine_whistle/vm/instructions/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,11 +15,12 @@ Implementations of the EVM stack related instructions. Require functools. Require ethereum_types.numeric. -Require tangerine_whistle.vm.exceptions. -Require tangerine_whistle.vm.gas. -Require tangerine_whistle.vm.memory. +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 : M unit := +Definition pop (evm : Evm) : M unit := (* Remove item from stack. @@ -28,18 +30,22 @@ Definition pop : M unit := The current EVM frame. *) - do* stack.["pop"] (| - evm.["stack"] - |) in - do* gas.charge_gas (| + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_BASE - |) in + |) ]] in (* TODO statement *) - (* TODO statement *) - + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. -Definition push_n : M unit := +Definition push_n (evm : Evm) (num_bytes : int) : M unit := (* Pushes a N-byte immediate onto the stack. @@ -54,29 +60,33 @@ Definition push_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in - let* data_to_push := ethereum_types.numeric.U256.["from_be_bytes"] (| - memory.buffer_read (| - evm.["code"], - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - num_bytes + |) ]] 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 - do* stack.["push"] (| - evm.["stack"], - data_to_push - |) in - (* TODO statement *) - - -Definition dup_n : M unit := + |) 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. @@ -91,20 +101,26 @@ Definition dup_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) - let* data_to_duplicate := (* TODO expression *) in - do* stack.["push"] (| - evm.["stack"], - data_to_duplicate - |) 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 : M unit := +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. @@ -123,11 +139,15 @@ Definition swap_n : M unit := *) (* TODO statement *) - do* gas.charge_gas (| + do* [[ gas.charge_gas ~(| evm, gas.GAS_VERY_LOW - |) in + |) ]] in (* TODO statement *) (* TODO assignment *) - (* 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/storage.v b/coq/ethereum/tangerine_whistle/vm/instructions/storage.v index 578f5bb6ae..1bc4a4a5aa 100644 --- a/coq/ethereum/tangerine_whistle/vm/instructions/storage.v +++ b/coq/ethereum/tangerine_whistle/vm/instructions/storage.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Storage Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,11 +14,12 @@ Implementations of the EVM storage related instructions. *) Require ethereum_types.numeric. -Require tangerine_whistle.state. -Require tangerine_whistle.vm.gas. -Require tangerine_whistle.vm.stack. +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 : M unit := +Definition sload (evm : Evm) : M unit := (* Loads to the stack, the value corresponding to a certain key from the storage of the current account. @@ -28,28 +30,36 @@ Definition sload : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - do* gas.charge_gas (| + |) in + ]] in + do* [[ gas.charge_gas ~(| evm, gas.GAS_SLOAD - |) in - let* value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in - do* stack.push (| - evm.["stack"], - value - |) in - (* TODO statement *) - + |) ]] 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 : M unit := +Definition sstore (evm : Evm) : M unit := (* Stores a value at a certain key in the current context's storage. @@ -59,30 +69,40 @@ Definition sstore : M unit := The current EVM frame. *) - let* key := stack.pop (| - evm.["stack"] - |).["to_be_bytes32"] (| + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| - |) in - let* new_value := stack.pop (| - evm.["stack"] - |) in - let* current_value := state.get_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key - |) in + |) 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - do* state.set_storage (| - evm.["env"].["state"], - evm.["message"].["current_target"], - key, - new_value - |) in - (* TODO statement *) - + 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.v b/coq/ethereum/tangerine_whistle/vm/instructions/system.v index fdf3bbe166..b06a9867ef 100644 --- a/coq/ethereum/tangerine_whistle/vm/instructions/system.v +++ b/coq/ethereum/tangerine_whistle/vm/instructions/system.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) System Instructions ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,14 +15,15 @@ Implementations of the EVM system related instructions. Require ethereum_types.bytes. Require ethereum_types.numeric. -Require tangerine_whistle.fork_types. -Require tangerine_whistle.state. -Require tangerine_whistle.utils.address. -Require tangerine_whistle.vm.gas. -Require tangerine_whistle.vm.memory. -Require tangerine_whistle.vm.stack. +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 : M unit := +Definition create (evm : Evm) : M unit := (* Creates a new account with associated code. @@ -31,47 +33,71 @@ Definition create : M unit := The current EVM frame. *) (* TODO statement *) - let* endowment := stack.pop (| - evm.["stack"] - |) in - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - let* create_message_gas := gas.max_message_call_gas (| - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |) - |) in - (* TODO statement *) - (* TODO statement *) - let* sender_address := evm.["message"].["current_target"] in - let* sender := state.get_account (| - evm.["env"].["state"], - sender_address - |) in - let* contract_address := utils.address.compute_contract_address (| - evm.["message"].["current_target"], - state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["nonce"] - |) in - (* TODO statement *) + |) ]] 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_ : M unit := +Definition return_ (evm : Evm) : M unit := (* Halts execution returning output data. @@ -80,65 +106,83 @@ Definition return_ : M unit := evm : The current EVM frame. *) - let* memory_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) + |) ]] 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 : M unit := +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 *) - let* call_data := memory.memory_read_bytes (| - evm.["memory"], - memory_input_start_position, - memory_input_size - |) in - let* code := state.get_account (| - evm.["env"].["state"], - code_address - |).["code"] in - let* child_message := Message (| + 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 - let* child_evm := process_message (| - child_message, - evm.["env"] - |) in + |) 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 *) - let* actual_output_size := min (| - memory_output_size, - ethereum_types.numeric.U256 (| - len (| - child_evm.["output"] + 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 - do* memory.memory_write (| - evm.["memory"], + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), memory_output_start_position, (* TODO expression *) - |) in - + |) ]] in + M.pure tt. -Definition call : M unit := +Definition call (evm : Evm) : M unit := (* Message-call into an account. @@ -147,64 +191,96 @@ Definition call : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* to := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* _account_exists := state.account_exists (| - evm.["env"].["state"], - to - |) in - let* create_gas_cost := (* TODO expression *) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition callcode (evm : Evm) : M unit := (* Message-call into this account with alternative account’s code. @@ -213,60 +289,90 @@ Definition callcode : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* value := stack.pop (| - evm.["stack"] - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* to := evm.["message"].["current_target"] in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* transfer_gas_cost := (* TODO expression *) in - let* message_call_gas := gas.calculate_message_call_gas (| - value, - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - (* TODO expression *) - |) in - do* gas.charge_gas (| + 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 - (* TODO statement *) - let* sender_balance := state.get_account (| - evm.["env"].["state"], - evm.["message"].["current_target"] - |).["balance"] in - (* TODO statement *) + |) ]] 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 : M unit := +Definition selfdestruct (evm : Evm) : M unit := (* Halt execution and register account for later deletion. @@ -275,50 +381,64 @@ Definition selfdestruct : M unit := evm : The current EVM frame. *) - let* beneficiary := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* gas_cost := gas.GAS_SELF_DESTRUCT in + 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 *) - let* originator := evm.["message"].["current_target"] in - let* refunded_accounts := evm.["accounts_to_delete"] in - let* parent_evm := evm.["message"].["parent_evm"] 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 (| + do* [[ gas.charge_gas ~(| evm, - gas_cost - |) in - let* beneficiary_balance := state.get_account (| - evm.["env"].["state"], - beneficiary - |).["balance"] in - let* originator_balance := state.get_account (| - evm.["env"].["state"], - originator - |).["balance"] in - do* state.set_account_balance (| - evm.["env"].["state"], - beneficiary, + 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 (| - evm.["env"].["state"], - originator, - ethereum_types.numeric.U256 (| - (* 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* evm.["accounts_to_delete"].["add"] (| - originator - |) in + |) ]] 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 : M unit := +Definition delegatecall (evm : Evm) : M unit := (* Message-call into an account. @@ -327,60 +447,82 @@ Definition delegatecall : M unit := evm : The current EVM frame. *) - let* gas := ethereum_types.numeric.Uint (| - stack.pop (| - evm.["stack"] - |) - |) in - let* code_address := utils.address.to_address (| - stack.pop (| - evm.["stack"] - |) - |) in - let* memory_input_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_input_size := stack.pop (| - evm.["stack"] - |) in - let* memory_output_start_position := stack.pop (| - evm.["stack"] - |) in - let* memory_output_size := stack.pop (| - evm.["stack"] - |) in - let* extend_memory := gas.calculate_gas_extend_memory (| - evm.["memory"], - (* TODO expression *) - |) in - let* message_call_gas := gas.calculate_message_call_gas (| - ethereum_types.numeric.U256 (| + 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 *) - |), - gas, - ethereum_types.numeric.Uint (| - evm.["gas_left"] - |), - extend_memory.["cost"], - gas.GAS_CALL - |) in - do* gas.charge_gas (| + |) 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 - (* TODO statement *) - do* generic_call (| + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| evm, - message_call_gas.["stipend"], - evm.["message"].["value"], - evm.["message"].["caller"], - evm.["message"].["current_target"], - code_address, - (* TODO expression *), - memory_input_start_position, - memory_input_size, - memory_output_start_position, - memory_output_size - |) in - (* TODO statement *) - + 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.v b/coq/ethereum/tangerine_whistle/vm/interpreter.v index f8d35c19b1..cc25a8e55c 100644 --- a/coq/ethereum/tangerine_whistle/vm/interpreter.v +++ b/coq/ethereum/tangerine_whistle/vm/interpreter.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Interpreter ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,17 +18,18 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.trace. -Require tangerine_whistle.blocks. -Require tangerine_whistle.fork_types. -Require tangerine_whistle.state. -Require tangerine_whistle.vm. -Require tangerine_whistle.vm.gas. -Require tangerine_whistle.vm.precompiled_contracts.mapping. -Require tangerine_whistle.vm.exceptions. -Require tangerine_whistle.vm.instructions. -Require tangerine_whistle.vm.runtime. - -Definition process_message_call : M unit := +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`. @@ -47,19 +49,21 @@ Definition process_message_call : M unit := *) (* TODO statement *) (* TODO statement *) - let* tx_end := ethereum.trace.TransactionEnd (| - (* TODO expression *), - evm.["output"], - evm.["error"] - |) in - do* ethereum.trace.evm_trace (| - evm, - tx_end - |) in + 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 : M unit := +Definition process_create_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -75,22 +79,24 @@ Definition process_create_message : M unit := evm: :py:class:`~ethereum.tangerine_whistle.vm.Evm` Items containing execution specific objects. *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.destroy_storage (| - env.["state"], - message.["current_target"] - |) in - let* evm := process_message (| - message, - env - |) in + 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 : M unit := +Definition process_message (message : Message) (env : Environment) : M Evm := (* Executes a call to create a smart contract. @@ -107,23 +113,25 @@ Definition process_message : M unit := Items containing execution specific objects *) (* TODO statement *) - do* state.begin_transaction (| - env.["state"] - |) in - do* state.touch_account (| - env.["state"], - message.["current_target"] - |) in + 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 *) - let* evm := execute_code (| - message, - env - |) in + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition execute_code : M unit := +Definition execute_code (message : Message) (env : Environment) : M Evm := (* Executes bytecode present in the `message`. @@ -139,13 +147,19 @@ Definition execute_code : M unit := evm: `ethereum.vm.EVM` Items containing execution specific objects *) - let* code := message.["code"] in - let* valid_jump_destinations := runtime.get_valid_jump_destinations (| - code - |) in - let* evm := Evm (| - - |) in + 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.v b/coq/ethereum/tangerine_whistle/vm/memory.v index 94b6a44639..88b516318f 100644 --- a/coq/ethereum/tangerine_whistle/vm/memory.v +++ b/coq/ethereum/tangerine_whistle/vm/memory.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Memory ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.utils.byte. -Definition memory_write : M unit := +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := (* Writes to memory. @@ -30,9 +31,9 @@ Definition memory_write : M unit := Data to write to memory. *) (* TODO assignment *) + M.pure tt. - -Definition memory_read_bytes : M unit := +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := (* Read bytes from memory. @@ -51,9 +52,9 @@ Definition memory_read_bytes : M unit := Data read from memory. *) (* TODO statement *) + M.pure tt. - -Definition buffer_read : M unit := +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := (* Read bytes from a buffer. Padding with zeros if necessary. @@ -72,4 +73,4 @@ Definition buffer_read : M unit := Data read from memory. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.v b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.v index 41f2c4b229..7d2fa2b4e2 100644 --- a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.v +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,4 +14,4 @@ Addresses of precompiled contracts and mappings to their implementations. *) -Require tangerine_whistle.utils.hexadecimal. +Require ethereum.tangerine_whistle.utils.hexadecimal. diff --git a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.v index b10d7b92f0..054bb8ec41 100644 --- a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.v +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,11 +17,11 @@ Require ethereum_types.numeric. Require ethereum.crypto.elliptic_curve. Require ethereum.crypto.hash. Require ethereum.utils.byte. -Require tangerine_whistle.vm. -Require tangerine_whistle.vm.gas. -Require tangerine_whistle.vm.memory. +Require ethereum.tangerine_whistle.vm. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.memory. -Definition ecrecover : M unit := +Definition ecrecover (evm : Evm) : M unit := (* Decrypts the address using elliptic curve DSA recovery mechanism and writes the address to output. @@ -30,64 +31,80 @@ Definition ecrecover : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - do* vm.gas.charge_gas (| + 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 - let* message_hash_bytes := vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) - |) - |) in - let* message_hash := ethereum.crypto.hash.Hash32 (| - message_hash_bytes - |) in - let* v := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + ethereum_types.numeric.U256 ~(| + 32 |) - |) - |) in - let* r := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 - let* s := ethereum_types.numeric.U256.["from_be_bytes"] (| - vm.memory.buffer_read (| - data, - ethereum_types.numeric.U256 (| - (* TODO expression *) - |), - ethereum_types.numeric.U256 (| - (* TODO expression *) + |) 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 + ]] 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 *) - let* address := (* TODO expression *) in - let* padded_address := ethereum.utils.byte.left_pad_zero_bytes (| - address, - (* TODO expression *) - |) in + 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.v b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.v index 740ea286f6..9d3f2ce866 100644 --- a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.v +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,10 +15,10 @@ Implementation of the `IDENTITY` precompiled contract. Require ethereum_types.numeric. Require ethereum.utils.numeric. -Require tangerine_whistle.vm. -Require tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm. +Require ethereum.tangerine_whistle.vm.gas. -Definition identity : M unit := +Definition identity (evm : Evm) : M unit := (* Writes the message data to output. @@ -26,11 +27,15 @@ Definition identity : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* vm.gas.charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.v b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.v index f129cdd4e4..e9204239b8 100644 --- a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.v +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.v @@ -1,3 +1,4 @@ +(* Generated *) (* Precompiled Contract Addresses ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,8 +14,9 @@ Mapping of precompiled contracts their implementations. *) Require typing. -Require tangerine_whistle.fork_types. -Require tangerine_whistle.vm.precompiled_contracts.ecrecover. -Require tangerine_whistle.vm.precompiled_contracts.identity. -Require tangerine_whistle.vm.precompiled_contracts.ripemd160. -Require tangerine_whistle.vm.precompiled_contracts.sha256. +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.v b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.v index bc5e73dd3c..fe2c66bbe6 100644 --- a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.v +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `RIPEMD160` precompiled contract. *) -Definition ripemd160 : M unit := +Definition ripemd160 (evm : Evm) : M unit := (* Writes the ripemd160 hash to output. @@ -22,21 +23,29 @@ Definition ripemd160 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 - let* hash_bytes := hashlib.["new"] (| - (* TODO expression *), - data - |).["digest"] (| - - |) in - let* padded_hash := left_pad_zero_bytes (| - hash_bytes, - (* TODO expression *) - |) in + |) ]] 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.v b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.v index da6972d411..3ba3ffe7aa 100644 --- a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.v +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +14,7 @@ Implementation of the `SHA256` precompiled contract. *) -Definition sha256 : M unit := +Definition sha256 (evm : Evm) : M unit := (* Writes the sha256 hash to output. @@ -22,11 +23,15 @@ Definition sha256 : M unit := evm : The current EVM frame. *) - let* data := evm.["message"].["data"] in - let* word_count := (* TODO expression *) in - do* charge_gas (| + 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 + |) ]] in (* TODO assignment *) - + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/runtime.v b/coq/ethereum/tangerine_whistle/vm/runtime.v index 7876a3db70..b43bafdb58 100644 --- a/coq/ethereum/tangerine_whistle/vm/runtime.v +++ b/coq/ethereum/tangerine_whistle/vm/runtime.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Runtime Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Runtime related operations used while executing EVM code. Require typing. Require ethereum_types.numeric. -Require tangerine_whistle.vm.instructions. +Require ethereum.tangerine_whistle.vm.instructions. -Definition get_valid_jump_destinations : M unit := +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := (* Analyze the evm code to obtain the set of valid jump destinations. @@ -38,12 +39,16 @@ Definition get_valid_jump_destinations : M unit := valid_jump_destinations: `Set[Uint]` The set of valid jump destinations in the code. *) - let* valid_jump_destinations := set (| - - |) in - let* pc := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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.v b/coq/ethereum/tangerine_whistle/vm/stack.v index 04f01207b7..88ada3772d 100644 --- a/coq/ethereum/tangerine_whistle/vm/stack.v +++ b/coq/ethereum/tangerine_whistle/vm/stack.v @@ -1,3 +1,4 @@ +(* Generated *) (* Ethereum Virtual Machine (EVM) Stack ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -14,9 +15,9 @@ Implementation of the stack operators for the EVM. Require typing. Require ethereum_types.numeric. -Require tangerine_whistle.vm.exceptions. +Require ethereum.tangerine_whistle.vm.exceptions. -Definition pop : M unit := +Definition pop (stack : (* TODO type *)) : M U256 := (* Pops the top item off of `stack`. @@ -33,9 +34,9 @@ Definition pop : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition push : M unit := +Definition push (stack : (* TODO type *)) (value : U256) : M unit := (* Pushes `value` onto `stack`. @@ -50,4 +51,4 @@ Definition push : M unit := *) (* TODO statement *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/trace.v b/coq/ethereum/trace.v index cfb74ecc24..e5b06c80ab 100644 --- a/coq/ethereum/trace.v +++ b/coq/ethereum/trace.v @@ -1,3 +1,4 @@ +(* Generated *) (* Defines the functions required for creating EVM traces during execution. @@ -17,10 +18,10 @@ See [EIP-3155] for more details on EVM traces. *) -Definition discard_evm_trace : M unit := +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__.v b/coq/ethereum/utils/__init__.v index 782ba6d087..9b0eb36c08 100644 --- a/coq/ethereum/utils/__init__.v +++ b/coq/ethereum/utils/__init__.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility functions used in this specification. *) @@ -5,10 +6,10 @@ Utility functions used in this specification. Require dataclasses. Require typing. -Definition has_field : M unit := +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.v b/coq/ethereum/utils/byte.v index 436e401845..f0b8f2d86d 100644 --- a/coq/ethereum/utils/byte.v +++ b/coq/ethereum/utils/byte.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Byte Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require typing. Require ethereum_types.bytes. Require ethereum_types.numeric. -Definition left_pad_zero_bytes : M unit := +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`. @@ -33,9 +34,9 @@ Definition left_pad_zero_bytes : M unit := left padded byte string of given `size`. *) (* TODO statement *) + M.pure tt. - -Definition right_pad_zero_bytes : M unit := +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`. @@ -52,4 +53,4 @@ Definition right_pad_zero_bytes : M unit := right padded byte string of given `size`. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/utils/hexadecimal.v b/coq/ethereum/utils/hexadecimal.v index 23bfddfc14..867a45520c 100644 --- a/coq/ethereum/utils/hexadecimal.v +++ b/coq/ethereum/utils/hexadecimal.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Hexadecimal Strings ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +17,7 @@ Require ethereum_types.bytes. Require ethereum_types.numeric. Require ethereum.crypto.hash. -Definition has_hex_prefix : M unit := +Definition has_hex_prefix (hex_string : str) : M bool := (* Check if a hex string starts with hex prefix (0x). @@ -31,9 +32,9 @@ Definition has_hex_prefix : M unit := Boolean indicating whether the hex string has 0x prefix. *) (* TODO statement *) + M.pure tt. - -Definition remove_hex_prefix : M unit := +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. @@ -50,9 +51,9 @@ Definition remove_hex_prefix : M unit := *) (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bytes : M unit := +Definition hex_to_bytes (hex_string : str) : M Bytes := (* Convert hex string to bytes. @@ -67,9 +68,9 @@ Definition hex_to_bytes : M unit := Byte stream corresponding to the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bytes8 : M unit := +Definition hex_to_bytes8 (hex_string : str) : M Bytes8 := (* Convert hex string to 8 bytes. @@ -84,9 +85,9 @@ Definition hex_to_bytes8 : M unit := 8-byte stream corresponding to the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bytes20 : M unit := +Definition hex_to_bytes20 (hex_string : str) : M Bytes20 := (* Convert hex string to 20 bytes. @@ -101,9 +102,9 @@ Definition hex_to_bytes20 : M unit := 20-byte stream corresponding to the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bytes32 : M unit := +Definition hex_to_bytes32 (hex_string : str) : M Bytes32 := (* Convert hex string to 32 bytes. @@ -118,9 +119,9 @@ Definition hex_to_bytes32 : M unit := 32-byte stream corresponding to the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_bytes256 : M unit := +Definition hex_to_bytes256 (hex_string : str) : M Bytes256 := (* Convert hex string to 256 bytes. @@ -135,9 +136,9 @@ Definition hex_to_bytes256 : M unit := 256-byte stream corresponding to the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_hash : M unit := +Definition hex_to_hash (hex_string : str) : M Hash32 := (* Convert hex string to hash32 (32 bytes). @@ -152,9 +153,9 @@ Definition hex_to_hash : M unit := 32-byte stream obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_uint : M unit := +Definition hex_to_uint (hex_string : str) : M Uint := (* Convert hex string to Uint. @@ -169,9 +170,9 @@ Definition hex_to_uint : M unit := The unsigned integer obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_u64 : M unit := +Definition hex_to_u64 (hex_string : str) : M U64 := (* Convert hex string to U64. @@ -186,9 +187,9 @@ Definition hex_to_u64 : M unit := The U64 integer obtained from the given hexadecimal string. *) (* TODO statement *) + M.pure tt. - -Definition hex_to_u256 : M unit := +Definition hex_to_u256 (hex_string : str) : M U256 := (* Convert hex string to U256. @@ -203,4 +204,4 @@ Definition hex_to_u256 : M unit := The U256 integer obtained from the given hexadecimal string. *) (* TODO statement *) - + M.pure tt. diff --git a/coq/ethereum/utils/numeric.v b/coq/ethereum/utils/numeric.v index 5e2ab66ba7..68a18d2cb1 100644 --- a/coq/ethereum/utils/numeric.v +++ b/coq/ethereum/utils/numeric.v @@ -1,3 +1,4 @@ +(* Generated *) (* Utility Functions For Numeric Operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,7 +16,7 @@ Numeric operations specific utility functions used in this specification. Require typing. Require ethereum_types.numeric. -Definition get_sign : M unit := +Definition get_sign (value : int) : M int := (* Determines the sign of a number. @@ -31,9 +32,9 @@ Definition get_sign : M unit := The return value is based on math signum function. *) (* TODO statement *) + M.pure tt. - -Definition ceil32 : M unit := +Definition ceil32 (value : Uint) : M Uint := (* Converts a unsigned integer to the next closest multiple of 32. @@ -49,14 +50,18 @@ Definition ceil32 : M unit := else it returns the smallest multiple of 32 that is greater than `value`. *) - let* ceiling := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* remainder := (* TODO expression *) in + 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 : M unit := +Definition is_prime (number : SupportsInt) : M bool := (* Checks if `number` is a prime number. @@ -70,15 +75,17 @@ Definition is_prime : M unit := is_number_prime : `bool` Boolean indicating if `number` is prime or not. *) - let* number := int (| - number - |) in + 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 : M unit := +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 @@ -96,12 +103,14 @@ Definition le_bytes_to_uint32_sequence : M unit := Sequence of U32 numbers obtained from the little endian byte stream. *) - let* sequence := (* TODO expression *) in + do* M.assign "sequence" [[ + (* TODO expression *) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition le_uint32_sequence_to_bytes : M unit := +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 @@ -126,12 +135,14 @@ Definition le_uint32_sequence_to_bytes : M unit := result : `bytes` The byte stream obtained from the little endian U32 stream. *) - let* result_bytes := (* TODO expression *) in + do* M.assign "result_bytes" [[ + (* TODO constant *) in + ]] in (* TODO statement *) (* TODO statement *) + M.pure tt. - -Definition le_uint32_sequence_to_uint : M unit := +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 @@ -148,13 +159,15 @@ Definition le_uint32_sequence_to_uint : M unit := The Uint number obtained from the conversion of the little endian U32 stream. *) - let* sequence_as_bytes := le_uint32_sequence_to_bytes (| - sequence - |) in + 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 : M unit := +Definition taylor_exponential (factor : Uint) (numerator : Uint) (denominator : Uint) : M Uint := (* Approximates factor * e ** (numerator / denominator) using Taylor expansion. @@ -174,13 +187,19 @@ Definition taylor_exponential : M unit := The approximation of factor * e ** (numerator / denominator). *) - let* i := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* output := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in - let* numerator_accumulated := (* TODO expression *) in + 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.v b/coq/ethereum/utils/safe_arithmetic.v index 12986a00d1..b0098f6c2b 100644 --- a/coq/ethereum/utils/safe_arithmetic.v +++ b/coq/ethereum/utils/safe_arithmetic.v @@ -1,3 +1,4 @@ +(* Generated *) (* Safe Arithmetic for U256 Integer Type ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -15,7 +16,7 @@ Safe arithmetic utility functions for U256 integer type. Require typing. Require ethereum_types.numeric. -Definition u256_safe_add : M unit := +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. @@ -42,9 +43,9 @@ Definition u256_safe_add : M unit := else `exception_type` is raised. *) (* TODO statement *) + M.pure tt. - -Definition u256_safe_multiply : M unit := +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. @@ -70,8 +71,10 @@ Definition u256_safe_multiply : M unit := one raised by `U256` when `U256.value > U256.MAX_VALUE` else `exception_type` is raised. *) - let* result := ethereum_types.numeric.Uint (| - (* TODO expression *) - |) in + 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 index ba259bfac5..3304eb72fa 100644 --- a/coq/translate.py +++ b/coq/translate.py @@ -2,11 +2,12 @@ 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/ethereum") +source_root_dir = Path("../src") def indent(text: str) -> str: @@ -21,46 +22,96 @@ def indent(text: str) -> str: ) -def to_coq_expression(import_aliases: dict[str, str], node: ast.expr) -> str: - if isinstance(node, ast.Name): - if node.id in import_aliases: - return import_aliases[node.id] + "." + node.id - return node.id +@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(import_aliases, node.func) + " (|\n" + \ + to_coq_expression(environment, node.func) + " ~(|\n" + \ indent( - ',\n'.join(to_coq_expression(import_aliases, arg) for arg in node.args) + ',\n'.join(to_coq_expression(environment, arg) for arg in node.args) ) + "\n" + \ "|)" - if isinstance(node, ast.Attribute): - return \ - to_coq_expression(import_aliases, node.value) + ".[\"" + node.attr + "\"]" + 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(import_aliases: dict[str, str], node: ast.stmt) -> str: +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(import_aliases, node.value) + " in" + "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 \ - "let* " + node.targets[0].id + " := " + \ - to_coq_expression(import_aliases, node.value) + " in" + "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_function_def(import_aliases: dict[str, str], node: ast.FunctionDef) -> str: - output = f"Definition {node.name} : M unit :=\n" - +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(import_aliases, statement)) + "\n" + output += indent(to_coq_statement(local_environment, statement)) + "\n" + output += indent("M.pure tt.") return output @@ -76,9 +127,12 @@ def dir_parent_n_times(dir_path: Path, n: int) -> Path: def to_coq(dir_path: Path, tree: ast.AST) -> str: if isinstance(tree, ast.Module): - output = "" + output = "(* Generated *)\n" mode: ToCoqMode = 'header_comment' - import_aliases: dict[str, str] = {} + environment: Environment = Environment( + import_aliases={}, + local_variables=set() + ) for node in tree.body: if mode == 'header_comment': @@ -90,23 +144,23 @@ def to_coq(dir_path: Path, tree: ast.AST) -> str: return "No description available at the beginning of the file" if mode == 'imports': if isinstance(node, ast.ImportFrom): - if node.module is not None: - for alias in node.names: - import_aliases[alias.name] = node.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}{node.module}.\n" + 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(import_aliases, node) + "\n" + output += to_coq_function_def(environment, node) + "\n" return output @@ -121,7 +175,7 @@ def translate_file(file_path: Path) -> None: with open(file_path) as f: source = f.read() tree = ast.parse(source) - output_file_path = Path("ethereum") / file_path.relative_to(source_root_dir) + 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)